はじめに
前回の続き.
コマンドパターン (Command Pattern) と Visitor Pattern で なにが違うのかよくわからなかったので, 比較しつつ, Command Pattern を実装してみた.
Command Pattern とは
動作を表現するオブジェクト. 動作とそれに伴うパラメータをカプセル化したもの.
特徴
- 
Command オブジェクトは, 手続きに必要なパラメータの一時格納場所として便利. 関数呼び出しのためのパラメータを集めて, 後で使用するためにコマンドを保存しておくことができる.
 - 
関数呼び出しのためのパラメータを集めて, 後で使用するためにコマンドを保存しておくことができる. 保存されたデータ構造に対する追加, 削除が可能になる.
 - 
コマンドの生成と実行のタイミングの分離.
 
Visitor パターンとの比較
わかりやすいように, Command ということばをここでは Visitor とする.
Visitor Pattern
オブジェクトの関係
- Receiver は たくさん.
 - Visitor は 単一.
 
データと操作の関係
- データは Visitor, 操作は Receiver がもつ.
 - Receiver は Visitor によって異なる操作をする.
 
Command Pattern
オブジェクトの関係
- Receiver は 単一.
 - Visitor は たくさん.
 
データと操作の関係
- データと操作は Visitor がもつ.
 - Receiver は Visitor によって同じ操作を実施する.
 
Code
前回の Visitor のコードを少し残しつつ, コードを改良してみた.
Invoker というコマンドを貯めておくデータ構造を追加した.
import java.util.Iterator;
import java.util.Stack;
class CommandSample {
    ////////////////////
    // Data
    ////////////////////
    abstract public static class Command {
    public void setReceiver (Receiver receiver){}
        public abstract void execute ();
        // abstract public void accept (Receiver printer);
    }
    public static class Data1 extends Command {
        protected Receiver receiver;
        private String str1 = "Suzuki";
        private String str2 = "Ichiro";
        // データは隠蔽 getter は提供しない
        // public String getStr1 () {
        //  return "Suzuki";
        // }
        // public String getStr2 () {
        //  return "Ichiro";
        // }
    public void setReceiver (Receiver receiver){
            this.receiver = receiver;
    }
    public void execute (){
            receiver.action (str1 + " " + str2);
    }       
        // public void accept (Receiver printer) {
        //  printer.visit (this);
        // }
    }
    public static class Data2 extends Command {
        protected Receiver receiver;
        private String str = "Jonney";
        // データは隠蔽, getter は提供しない
        // public String getStr () {
        //  return "Jonney";
        // }
    public void setReceiver (Receiver receiver){
            this.receiver = receiver;
    }
        // public void accept (Receiver printer) {
        //  printer.visit (this);
        // }
    public void execute (){
            receiver.action (str);
    }       
    }
    public interface Receiver {
        // public void visit (Data1 data);
        // public void visit (Data2 data);
        public abstract void action (String msg);
    }
    public static class NamePrinter implements Receiver {
        // コマンドに応じて処理を変更しない.
        // public void visit (Data1 data) {
        //  String str1 = data.getStr1 ();
        //  String str2 = data.getStr2 ();
        //  System.out.println (str1 + " " + str2);
        // }
        // public void visit (Data2 data) {
        //  String str = data.getStr ();
        //  System.out.println (str);           
        // }
    public void action (String msg){
            System.out.println (msg);
    }       
    }
    ////////////////////
    // Invoker
    ////////////////////
    public static class Invoker{
    private Stack<Command> commands = new Stack<Command>();
    public void addCommand (Command command){
            commands.push (command);
    }
    public void execute (){
            for ( Command command : commands ) {
                command.execute ();
            }
    }
    }
    public static void main (String[] args) {
        NamePrinter name = new NamePrinter ();      
        Command data1, data2;
        Invoker invoker = new Invoker ();
        data1 = new Data1 ();
        data1.setReceiver (name);
        data2 = new Data2 ();
        data2.setReceiver (name);
        invoker.addCommand (data1);
        invoker.addCommand (data2);
        invoker.execute ();
    }
}
操作のカプセル化
Wikipedia の説明をみると, クロージャー機能に似ている気がした.
というわけで, 内部 (匿名, 無名) クラスを利用してみる.
import java.util.Iterator;
import java.util.Stack;
class CommandSample {
    ////////////////////
    // Command
    ////////////////////
    abstract public static class Command {
    public void setReceiver (Receiver receiver){}
        public abstract void execute ();
    }
    public static interface Executer {
        public void run ();
    }
    public static class Data1 extends Command {
        protected Receiver receiver;
        private String str1 = "Suzuki";
        private String str2 = "Ichiro";
    public void setReceiver (Receiver receiver){
            this.receiver = receiver;
    }
    public void execute () {
            receiver.action (new Executer () {
                    public void run () {
                        System.out.println (str1 + " " + str2);
                    }
                });
    }       
    }
    public static class Data2 extends Command {
        protected Receiver receiver;
        private String str = "Jonney";
    public void setReceiver (Receiver receiver){
            this.receiver = receiver;
    }
    public void execute () {
            receiver.action (new Executer () {
                    public void run () {
                        System.out.println (str);
                    }
                });
    }       
    }       
    ////////////////////
    // Receiver
    ////////////////////
    public interface Receiver {
        public abstract void action (Executer executer);
    }
    public static class NamePrinter implements Receiver {
    public void action (Executer executer){
            executer.run ();
    }       
    }
    ////////////////////
    // Invoker
    ////////////////////
    public static class Invoker{
    private Stack<Command> commands = new Stack<Command>();
    public void addCommand (Command command){
            commands.push (command);
    }
    public void execute (){
            for ( Command command : commands ) {
                command.execute ();
            }
    }
    }
    public static void main (String[] args) {
        NamePrinter name = new NamePrinter ();      
        Command data1, data2;
        Invoker invoker = new Invoker ();
        data1 = new Data1 ();
        data1.setReceiver (name);
        data2 = new Data2 ();
        data2.setReceiver (name);
        invoker.addCommand (data1);
        invoker.addCommand (data2);
        invoker.execute ();
    }
}
こうみると, Visitor Pattern にまた似てきた. 混乱してきたので今日はここまで.
- Command Pattern: call Command -> call Receiver -> call Executer
 - Visitor Pattern: call Receiver -> call Visitor