Java Mid Basic 〜Lv3_2_Javaの基本(リファクタリングLv2)ゲームループ付き

イントロダクション

前回は、リファクタリングをするのに「オブジェクト指向」について少し触れました。世間巷でいう「オブジェクト指向」というものとちょっと内容が違うように感じた人もいるかもしれません。がオブジェクト指向はこのように考えます。

  1. もの(オブジェクト)を大切にしましょう
  2. 再利用できるものは再利用しましょう
  3. 1クラスに1機能

ここで「つまり。。。」というのを考える必要があります。

オヴジェクト指向

ちょっと、寄り道をしてオブジェクト指向的なプログラミングのサンプルを作成したいと思います。「百聞は一見にしかず」といったところでしょうか(笑)

まずはメインメソッド

とりあえずは、メインメソッドを作成します。そして、標準入力を受けて無限ループする処理を作成します。さらに、「bye」と入力すると処理(アプリ)を終了する。という処理にします。まとめると以下のようになります。

  1. 標準入力を受ける
  2. "bye"と入力すると処理を終了する

これは、メインメソッドを定義するためのいわば「メインクラス」とします。

public class Lv3_1_RefactorLv2_Main {

    public static void main(String[] args) {
        // 標準入力
        Scanner input = new Scanner(System.in);

        while(true) {
            System.out.println("入力してください: ");
            String inStr = input.nextLine();
            if ("bye".equals(inStr)) {
                System.out.println("Good Byw");
                break;
            }
        }
    }
}
コマンド実行する

ここで「コマンド」を入力した時は、そのコマンドを実行するように作成します。イメージは下のような感じです。

上に記載したクラスが、メインクラスですが、まだコマンドマップを設定(コーディング)していません。次のようなコードをフィールドに追加します。private static List<CommandIF> cmdMap;メインメソッドで呼び出すために、「static」修飾子をつけます。そして、実装結果が下のコードになります。

public class Lv3_1_RefactorLv2_Main {
    /** コマンドマップ */
    private static  Map cmdMap;
    /** メインメソッド */
    public static void main(String[] args) {
        // 標準入力
        Scanner input = new Scanner(System.in);

        while(true) {
            System.out.println("入力してください: ");
            String inStr = input.nextLine();
            if ("bye".equals(inStr)) {
                System.out.println("Good Byw");
                break;
            }
        }
    }
}

ビルドエラーが!

そうなんです。このままだとビルドエラーが出ます。
存在しないクラス(インターフェースクラス)が使用されていればビルドエラーが出ます。なので作ります。

CommandIFインターフェースを作成

インターフェースの作成方法に関してはこちらの記事もご覧ください。インターフェースクラス、抽象クラスの作成方法に関して記載しています。
作成したものは下のようになります。

/**
 * コマンドインターフェース
* インターフェースは、処理内容を書きません。 * * @author takunoji * 2019/08/23 */ public interface CommandIF { /** コマンドを実行する */ public void execute(); }

インタフェースはメソッドの宣言のみなので、作るのは簡単なのです(笑)

そして、コマンドを設定するためのマップをインスタンス化します。

public class Lv3_1_RefactorLv2_Main {
    /** コマンドマップ */
    private static  Map cmdMap;
    public static void main(String[] args) {
        // コマンドの用意
        cmdMap = new HashMap();
        // 標準入力
        Scanner input = new Scanner(System.in);

        while(true) {
            System.out.println("入力してください: ");
            String inStr = input.nextLine();
            if ("bye".equals(inStr)) {
                System.out.println("Good Byw");
                break;
            }
        }
    }
}

インターフェースの実相

ここまできたらあとは、インターフェースの実相クラスを作成するだけです。
今回は、helloコマンドとreadyコマンドを作成します。どちらもコンソール出力するだけのシンプルなコマンドです。
helloコマンドは「HelloCommand」クラス、readyコマンドは「ReadyCommand」クラスに対応させます。
HelloCommand

public class HelloCommand implements CommandIF {

    /* (non-Javadoc)
     * @see jp.zenryoku.sample.lv3.refactor.CommandIF#execute()
     */
    @Override
    public void execute() {
        // TODO Auto-generated method stub
        System.out.println("Hello World!");
    }
}

ReadyCommand

public class ReadyCommand implements CommandIF {

    /* (non-Javadoc)
     * @see jp.zenryoku.sample.lv3.refactor.CommandIF#execute()
     */
    @Override
    public void execute() {
        // TODO Auto-generated method stub
        System.out.println("Ready?");
    }
}

どちらも、Eclipseでインターフェースのメソッドを自動生成したので、TODOコメントがついています。Eclipseの設定で出力しないように変更もできるので余裕があれば調べて見てください。

実装と実行結果

下のようになりました。

public class Lv3_1_RefactorLv2_Main {
    /** コマンドリスト */
    private static  Map cmdMap;
    public static void main(String[] args) {
        // コマンドの用意
        cmdMap = new HashMap();
        cmdMap.put("hello", new HelloCommand());
        cmdMap.put("ready", new ReadyCommand());
        // 標準入力
        Scanner input = new Scanner(System.in);

        while(true) {
            System.out.println("入力してください: ");
            String inStr = input.nextLine();
            CommandIF cmd = cmdMap.get(inStr);
            if (cmd != null) {
                cmd.execute();
            }
            if ("bye".equals(inStr)) {
                System.out.println("Good Byw");
                break;
            }
        }
    }
}

初めの実装とほぼ変わらないと思います。
ちょいと実行して見ます。

こんな感じで動きます。
でわでわ。。。