C#でデザインパターン~Commandパターン編~
2019-11-13
azblob://2022/11/11/eyecatch/2019-11-13-csharp-gof-commandpattern-000.jpg

Commandパターンとは

だんだんとデザインパターンに関する記事が増えてきたような気がしますが、今回は今回とてCommandパターンについて解説したいと思います。
Commandパターンは、動作をクラスの中に作成してカプセル化することで、それを纏めて管理できるようにするパターンです。
動作をカプセル化した部分をコマンドと呼び、それを管理するクラスを別途作って実装します。
コマンドはどれも同じ振舞いを継承させるので、管理する側からはその振舞いを呼び出すことで個々のコマンドを実行させることができます。

コードを見てみましょう

.Net Coreでプロジェクトを作成したら、まずはコマンドのインターフェースを定義します。
振舞いとしては、文字通り何かしらの振る舞いを実行することです。

interface ICommand
{
    public void excute();
}

次に、その振舞いを実装したコマンドのクラスを実装します。
今回は、単純にコメント出力を行います。

class Command : ICommand
{
    public void excute()
    {
        Console.WriteLine("コマンドを実行していますよ!");
    }
}

そうしたら、次はこれらのコマンドを纏めるクラスを作成します。
ここでは、コマンドを受け入れてストックしておき、すべてを順に実行するメソッドを作成しています。
ここで、他にもコマンドを消去したり好きなインデックスに保存されたコマンドを実行すっこうするするメソッドを作ることもできます。
Commandパターンにおいては、このようにCommandをまとめて管理する仕組みを作ることによって実行する動作を管理し、登録した複数のコマンドを実行することができるようになります。

class RemoteControl
{
    private List<ICommand> Commands = new List<ICommand>();

    public void ExcuteAllCommands()
    {
        Console.WriteLine("手持ちのコマンドを全部実行します");
        Commands.ForEach(x => x.excute());
    }
    public void AddCommand(ICommand command)
    {
        Commands.Add(command);
        Console.WriteLine("コマンドを追加しました");
    }
}

最後に、呼び出し側のコード(以降、クライアントコードと呼びます)におけるコードを作成します。
AddCommandを使ってコマンドを追加し、ExcuteAllCommandsですべてを実行します。

class Program
{
    static void Main(string[] args)
    {
        var remoteControl = new RemoteControl();
        remoteControl.AddCommand(new Command());
        remoteControl.ExcuteAllCommands();
        remoteControl.AddCommand(new Command());
        remoteControl.ExcuteAllCommands();
    }
}

うまくいけば、以下のような出力がなされるはずです。
ストックされているコマンドが増えると、コマンドを実行する回数が増えるのを確認できると思います。

コマンドを追加しました
コマンドを実行します
コマンドを実行していますよ!
コマンドを追加しました
コマンドを実行します
コマンドを実行していますよ!
コマンドを実行していますよ!

おわりに!

今回は、Commandパターンについて解説しました。
このパターンは、複数の動作を纏めて実行したい場合や、その実行する動作を場合に応じて入れ替えたい場合に特に有効です。
予定されたリクエストのキューや、トランザクションの作成にも使えるそうです。
こういった使い方について、一度使いどころを検討してみたいと思います。