Commandパターンとはデザインパターンの一種で、1つ1つのコマンド(命令)をそのままオブジェクトとして表現するパターンです。
コマンドをオブジェクトとして表現することで、コマンドの管理(追加・削除・実行)が可能になるというメリットがあります。
今回は、ファイルやフォルダを作成するコマンドを管理するサンプルコードを作成してみました。
Commandクラスが1つ1つのコマンドを表し、コマンドの管理はInvokerクラスで行い、コマンドの実際の処理はReceiverクラスで記述します。
【サンプルコード】
・Command.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// コマンドの抽象クラス public abstract class Command { protected String nameOfFileFolder; protected Receiver receiver; // コンストラクタ:生成するファイル名・フォルダ名をセット public Command(String nameOfFileFolder) { this.nameOfFileFolder = nameOfFileFolder; } // コマンドの受け手をセット public void setReceiver(Receiver receiver) { this.receiver = receiver; } // コマンドの受け手に処理を依頼 public abstract void execute(); } |
・ConcreteCommandForOperation.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 運用で使用するフォルダ・ファイル作成を指示するクラス public class ConcreteCommandForOperation extends Command { public ConcreteCommandForOperation(String nameOfFileFolder) { super(nameOfFileFolder); } public void execute() { receiver.action ("C:\\pleiades\\workspace\\Hello\\conf\\" + nameOfFileFolder); } } |
・ConcreteCommandForTemporary.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 一時フォルダ・ファイル作成を指示するクラス public class ConcreteCommandForTemporary extends Command { public ConcreteCommandForTemporary(String nameOfFileFolder) { super(nameOfFileFolder); } public void execute() { receiver.action ("C:\\tmp\\" + nameOfFileFolder); } } |
・Receiver.java
1 2 3 4 5 6 7 |
// コマンドの受け手の抽象クラス public interface Receiver { // 処理実行 public abstract void action(String path); } |
・ConcreteReceiverMkfil.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.io.File; import java.io.IOException; // ファイル作成を行うReceiver public class ConcreteReceiverMkfil implements Receiver { public void action(String path) { File file = new File(path + ".txt"); try { if (file.createNewFile()){ }else{ System.out.println(path + "作成に失敗しました。"); } } catch (IOException e) { e.printStackTrace(); } } } |
・ConcreteReceiverMkdir.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.io.File; // フォルダ作成を行うReceiver public class ConcreteReceiverMkdir implements Receiver { public void action(String path) { File file = new File(path); if (file.mkdir()){ }else{ System.out.println(path + "作成に失敗しました。"); } } } |
・Invoker.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import java.util.Iterator; import java.util.Stack; // コマンドの追加・取消・実行を管理するクラス public class Invoker { private Stack<Command> commandStack = new Stack<Command>(); // コマンドを追加する public void addCommnad(Command command) { commandStack.push(command); System.out.println (commandStack.size() + "個目のコマンドを登録しました。"); } // 直近のコマンドを削除する public void undoCommnad() { if(commandStack.empty()) { System.out.println("削除するコマンドがありません。"); } else { commandStack.pop(); System.out.println ((commandStack.size()+1) + "個目のコマンドを削除しました。"); } } // コマンドを順番に実行する public void execute() { System.out.println (commandStack.size() + "個のコマンドを実行します。"); Iterator<Command> itetator = commandStack.iterator(); while (itetator.hasNext()) { itetator.next().execute(); } System.out.println("コマンドを実行しました。"); } } |
・CommandMain.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// メインクラス public class CommandMain { public static void main(String[] args) { // 初期処理 Receiver receiverMkfil = new ConcreteReceiverMkfil(); Receiver receiverMkdir = new ConcreteReceiverMkdir(); Invoker invoker = new Invoker(); // コマンドの作成(5個) System.out.println("Aファイルを作成するコマンドを登録します。"); Command commandA = new ConcreteCommandForOperation("A"); commandA.setReceiver(receiverMkfil); invoker.addCommnad(commandA); System.out.println("Bフォルダを作成するコマンドを登録します。"); Command commandB = new ConcreteCommandForOperation("B"); commandB.setReceiver(receiverMkdir); invoker.addCommnad(commandB); System.out.println("C一時ファイルを作成するコマンドを登録します。"); Command commandC = new ConcreteCommandForTemporary("C"); commandC.setReceiver(receiverMkfil); invoker.addCommnad(commandC); System.out.println("D一時フォルダを作成するコマンドを登録します。"); Command commandD = new ConcreteCommandForTemporary("D"); commandD.setReceiver(receiverMkdir); invoker.addCommnad(commandD); System.out.println("Eファイルを作成するコマンドを登録します。"); Command commandE = new ConcreteCommandForOperation("E"); commandE.setReceiver(receiverMkfil); invoker.addCommnad(commandE); // 直近のコマンドの削除 invoker.undoCommnad(); // コマンドの実行 invoker.execute(); } } |
【実行結果】
・コンソール出力
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Aファイルを作成するコマンドを登録します。 1個目のコマンドを登録しました。 Bフォルダを作成するコマンドを登録します。 2個目のコマンドを登録しました。 C一時ファイルを作成するコマンドを登録します。 3個目のコマンドを登録しました。 D一時フォルダを作成するコマンドを登録します。 4個目のコマンドを登録しました。 Eファイルを作成するコマンドを登録します。 5個目のコマンドを登録しました。 5個目のコマンドを削除しました。 4個のコマンドを実行します。 コマンドを実行しました。 |
・ファイルやフォルダの生成確認
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
C:\pleiades\workspace\Hello\conf>cd C:\pleiades\workspace\Hello\conf C:\pleiades\workspace\Hello\conf>dir ドライブ C のボリューム ラベルは です ボリューム シリアル番号は です C:\pleiades\workspace\Hello\conf のディレクトリ 2020/02/08 10:02 <DIR> . 2020/02/08 10:02 <DIR> .. 2020/02/08 10:02 0 A.txt 2020/02/08 10:02 <DIR> B 1 個のファイル 0 バイト 3 個のディレクトリ 19,379,642,368 バイトの空き領域 C:\pleiades\workspace\Hello\conf> C:\pleiades\workspace\Hello\conf>cd C:\tmp\ C:\tmp>dir ドライブ C のボリューム ラベルは です ボリューム シリアル番号は です C:\tmp のディレクトリ 2020/02/08 10:02 <DIR> . 2020/02/08 10:02 <DIR> .. 2020/02/08 10:02 0 C.txt 2020/02/08 10:02 <DIR> D 1 個のファイル 0 バイト 3 個のディレクトリ 19,379,642,368 バイトの空き領域 C:\tmp> |
いかがでしたでしょうか。
デザインパターンに出てくる設計は、自力ではなかなか思いつかない勉強しがいがあるものが少なくないと思います。
「コマンドをオブジェクトとして表現することで、管理(追加・削除・実行)を可能とする」というCommandパターンの発想も、その一つなのではないかと思います。
ここしばらくの間はデザインパターンの紹介を行ってきましたが、一旦一区切りつけたいと思います。
次週からはまた別の観点で役に立つ記事を発信して行きたいと思いますので、今後もよろしくお願いします!
コメント