イントロダクション
前回は、リファクタリングをするのに「オブジェクト指向」について少し触れました。世間巷でいう「オブジェクト指向」というものとちょっと内容が違うように感じた人もいるかもしれません。がオブジェクト指向はこのように考えます。
- もの(オブジェクト)を大切にしましょう
- 再利用できるものは再利用しましょう
- 1クラスに1機能
ここで「つまり。。。」というのを考える必要があります。
オヴジェクト指向プログラミング
ちょっと、寄り道をしてオブジェクト指向的なプログラミングのサンプルを作成したいと思います。「百聞は一見にしかず」といったところでしょうか(笑)
<基本的なところを動画にしました。基本文法などです。>
<インターフェースの使い方例>
<インターフェースの使い方2:CommandIFを使う>
1.まずはメインメソッド
とりあえずは、メインメソッドを作成します。そして、標準入力を受けて無限ループする処理を作成します。さらに、「bye」と入力すると処理(アプリ)を終了する。という処理にします。まとめると以下のようになります。
- 標準入力を受ける
- "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; } } } }
2.コマンド実行する
ここで「コマンド」を入力した時は、そのコマンドを実行するように作成します。イメージは下のような感じです。
上に記載したクラスが、メインクラスですが、まだコマンドマップを設定(コーディング)していません。次のようなコードをフィールドに追加します。private static List<CommandIF> cmdMap;
メインメソッドで呼び出すために、「static」修飾子をつけます。そして、実装結果が下のコードになります。
public class Lv3_1_RefactorLv2_Main { /** コマンドマップ */ private static Map⁢String, CommandIF> 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<String, CommandIF> cmdMap; public static void main(String[] args) { // コマンドの用意 cmdMap = new HashMap<String, CommandIF>(); // 標準入力 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; } } } }
3.インターフェースの実装
ここまできたらあとは、インターフェースの実相クラスを作成するだけです。
今回は、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の設定で出力しないように変更もできるので余裕があれば調べて見てください。
Mapインターフェースの実装サンプル動画です。
4.実装と実行結果
下のようになりました。
public class Lv3_1_RefactorLv2_Main {
/** コマンドリスト */
private static Map<String, CommandIF> cmdMap;
public static void main(String[] args) {
// コマンドの用意
cmdMap = new HashMap<String, CommandIF>();
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;
}
}
}
}
初めの実装とほぼ変わらないと思います。
ちょいと実行して見ます。
こんな感じで動きます。
ポリモーフィズム
CommandIF(インタフェース)を使用したポリモーフィズムの実行動画があります。
でわでわ。。。
補足その1:リファクタリングの考え方
補足その2:クラスの役割分担を行う