Command パターン (命令, 操作をクラス (オブジェクト) で表現し, そのオブジェクトを切り替えるおで操作の切り替えを実現する)
[Command] = [命令]
このパターンでは, 一つ若しくは複数の命令を一つのオブジェクトで表現 (命令の詳細処理をカプセル化) する. また, 命令をオブジェクトとして管理するため, その命令の履歴管理, UNDO (取り消し) 機能の実装が容易に行える.
役割
- Command (命令):
命令のインタフェースを定義する
- ConcreteCommand[A|B] (具体的な命令):
[Command] のインタフェースを実装する
- Receiver (受信者):
[Command] の処理対象となるオブジェクトのインタフェース
- ConcreteReceiver (具体的な受信者):
[Receiver] のインタフェースを実装する. このように, [Receiver] インタフェースを介することで, 複数の命令の受取手 ([ConcreteReceiver]) を作成することができる.
- Invoker (起動者):
[Command] で定義されているインタフェースを呼び出す. また, 複数の [ConcreteCommand] を保持することにより, 命令の履歴管理機能, UNDO 機能等を提供する.
- Client (利用者):
ConcreteCommand[A|B] の初期設定 ([ConcreteReceiver] を命令の受取手としてセット), それらの命令を格納した [Invoker] の起動を行う. [Command] パターンを適用したクラスを利用し処理する.
クラス図
Command パターンのクラス図
ソースコード
- Command.java
| public abstract class Command{
public void setReceiver(Receiver receiver){}
public abstract void execute();
}
|
2-1. ConcreteCommandA.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | public class ConcreteCommandA extends Command{
private int id;
protected Receiver receiver;
private final String name = "A";
public ConcreteCommandA(int id){
this.id = id;
}
public void setReceiver(Receiver receiver){
this.receiver = receiver;
}
public void execute(){
receiver.action(name + ":" + id);
}
}
|
2-2. ConcreteCommandB.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | public class ConcreteCommandB extends Command{
private int id;
protected Receiver receiver;
private final String name = "B";
public ConcreteCommandB(int id){
this.id = id;
}
public void setReceiver(Receiver receiver){
this.receiver = receiver;
}
public void execute(){
receiver.action(name + ":" + id);
}
}
|
- Receiver.java
| public interface Receiver{
public abstract void action(String msg);
}
|
- ConcreteReceiver.java
| public class ConcreteReceiver implements Receiver{
public void action(String msg){
System.out.println(msg);
}
}
|
- 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 | import java.util.Iterator;
import java.util.Stack;
public class Invoker{
private Stack<Command> commands = new Stack<Command>();
public void addCommand(Command command){
commands.push(command);
}
public void undoCommand(){
Command command = (Command)commands.pop();
System.out.println();
System.out.println("undo - 削除された命令 DOWN");
command.execute();
System.out.println("undo - 削除された命令 UP");
System.out.println();
}
public void execute(){
Iterator<Command> it = commands.iterator();
while(it.hasNext()){
it.next().execute();
}
}
}
|
- Client.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 | public class Client{
public static void main(String[] args){
Command[] commandsA = new Command[5];
Command[] commandsB = new Command[5];
Receiver receiver = new ConcreteReceiver();
Invoker invoker = new Invoker();
for(int i = 0; i < commandsA.length; i++){
commandsA[i] = new ConcreteCommandA(i);
commandsA[i].setReceiver(receiver);
invoker.addCommand(commandsA[i]);
}
for(int i = 0; i < commandsB.length; i++){
commandsB[i] = new ConcreteCommandB(i);
commandsB[i].setReceiver(receiver);
invoker.addCommand(commandsB[i]);
}
invoker.execute();
invoker.undoCommand();
invoker.execute();
}
}
|
上記のプログラムの実行結果:
[wtopia Command]$ java Client
A:0
A:1
A:2
A:3
A:4
B:0
B:1
B:2
B:3
B:4
undo - 削除された命令 DOWN
B:4
undo - 削除された命令 UP
A:0
A:1
A:2
A:3
A:4
B:0
B:1
B:2
B:3