web-dev-qa-db-ja.com

なぜこのようにコマンドデザインパターンを実装するのですか?

コマンドデザインパターンを学習しようとしていますが、コマンドの動作と使用場所はすでにわかっていますが、実装については少し混乱しています。

そのため、オブジェクトをコンストラクタに渡すか、execute()関数の引数としてコンテキストを設定する必要があることを知っています。私が理解していないのは、すべてのコマンドを、実行するクラスのネストされたクラスとしてではなく、個別のクラスとして定義する必要があるのはなぜですか。コマンドを作成するときにオブジェクトが何であるかを既に知っている必要があるので(コンストラクターでコンテキストを設定する場合)、非常に多くの個別のクラスを持つことの意味は何ですか?

例えば:

これは私が通常見る典型的な実装です( このチュートリアルから 、私はそれを少し簡略化しました):

public class Television {
    public void on() {
        System.out.println("TV is on");
    }
}

public interface Command {
    public void execute();
}

public class TurnTVOn implements Command {

    ElectronicDevice theDevice;

    public TurnTVOn(ElectronicDevice newDevice){
        theDevice = newDevice;
    }

    public void execute() {
        theDevice.on();
    }   
}

//somewhere in main

Television newDevice = TVRemote.getDevice();

Command onCommand = new TurnTVOn(newDevice);

onCommand.execute()

次のようにしてみませんか。

public interface Command {
    public void execute();
}

public class Television {
    public void on() {
        System.out.println("TV is on");
    }

    public class TurnTVOn implements Command {
        public void execute() {
            on();
        }   
    }
}

//somewhere in main

Command onCommand = TVRemote.getDevice().TurnTVOn;

onCommand.execute()

答えはおそらく明白ですが、私は初心者であり、何かを完全に理解していないときに「愚かな」質問をするだけで、それだけで済むのではなく非常に役立ちます。

4
Wojtek Wencel

私が理解していないのは、すべてのコマンドを、実行するクラスのネストされたクラスとしてではなく、個別のクラスとして定義する必要があるのはなぜですか。

それが利用可能な場合、それは実行可能なオプションになる可能性があります。
コマンドは、[(レシーバー]]で操作しているものに結合される傾向があります。コマンドをネストされたクラスとして実装しました。これにより、コマンドが外部クラスのプライベートにアクセスできるようになります。
(C#を記述しています。C++を記述している場合、コマンドを実行するクラスのfriendとしてコマンドを宣言する場合があります。)

ただし、コマンドをレシーバーのネストされたクラスとして実装するオプションは、常に利用できるとは限りません。コマンドは、レシーバーを開発したグループとは異なるグループによって開発される場合があります。受信者がソースコードにアクセスできる場合は、ソースコードを変更する権限がある場合とない場合があります。

8
Nick Alexeev