dasukoの技術ブログ

現役エンジニアのブログです。

Commandパターン

はじめに

今回はデザインパターンの一つ、Commandパターンについてご紹介します。

Commandパターンとは

Wikipediaには以下のようにあります。

Command パターン(英: command pattern)はオブジェクト指向プログラミングにおけるデザインパターンの一つで、動作を表現するオブジェクトを示す。 Command オブジェクトは、動作とそれに伴うパラメータをカプセル化したものである。

Command パターン - Wikipediaより引用

Commandオブジェクトは特定の処理をするために必要なパラメータを格納したオブジェクトです。

ある処理を行う時に、Commandオブジェクトを定義して、それを優先度付きのQueueに積んで順番に処理したりします。

Commandパターンの具体的な使用例

以下はWikipediaより引用 - 複数のアンドゥ - トランザクション的振る舞い - プログレスバー - ウィザード - GUIのボタンとメニューの項目 - スレッドプール - マクロの記録 - ネットワーク - 並列処理 - 移動可能なコード

ThreadPoolについては以前、UnityでThreadPoolを使ってみた記事があるのでご参考ください

dasuko.hatenadiary.jp

クラス図

クラス図は大まかに以下のようになります。 f:id:dasuko:20200708224602p:plain

実装例

今回は動画をダウンロードするコマンドと画像をダウンロードするコマンドを実装してみました。

クラス図は以下です。 f:id:dasuko:20200709004726p:plain

// ICommand interface
public interface ICommand
{
    void Execute();
}

// IDownloader interface
public interface IDownloader
{
    // Download video
    void DownloadVideo(string url);

    // Download image
    void DownloadImage(string url);
}

// Downloader
public class Downloader : IDownloader
{
    public void DownloadVideo(string url)
    {
   // Download Video
    }

    public void DownloadImage(string url)
    {
          // Download Image
    }
}

// Video Download Command
public class VideoDownloadCommand : ICommand
{
    private IDownloader downloader;
    private string url;

    public VideoDownloadCommand(IDownloader downloader, string url)
    {
        this.downloader = downloader;
        this.url = url;
    }

    public void Execute()
    {
        downloader.DownloadVideo(url);
    }
}

// Image Download Command
public class ImageDownloadCommand : ICommand
{
    private IDownloader downloader;
    private string url;

    public ImageDownloadCommand(IDownloader downloader, string url)
    {
        this.downloader = downloader;
        this.url = url;
    }

    public void Execute()
    {
        downloader.DownloadImage(url);
    }
}

public class Client
{
    public void Do() {
        var downloader = new Downloader();
        var videoDownload = new VideoDownloadCommand(downloader, "url_to_video");
        var imageDownload = new ImageDownloadCommand(downloader, "url_to_image");

        videoDownload.Execute();
        imageDownload.Execute();
    }
}

まとめ

個人的にCommandは非同期処理で使うと便利なイメージがあります。

ダウンロードとか並列処理とか。。。

プログレスバーの更新に使っても便利そうですね。

今回のサンプルのようにダウンロードコマンドを共通インターフェースにして

Queueに積んで、ワーカースレッドで並列にダウンロードするようにするといいかもしれないです!

参考

Command パターン - Wikipedia