WinFormアプリで シンプルなコードからCommandパターンへ移行しよう

このチュートリアルでは、簡単な操作プログラムを作成し、それをより柔軟で拡張しやすい設計に改善する方法を学びます。まず、シンプルなコードを書き、その後、Commandパターンというデザインパターンを導入して、コードの設計を改善していきます。

ステップ1: シンプルなコードを作成する

以下のコードは、ボタンがクリックされたときにメッセージを表示する非常にシンプルなものです。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1Click(object sender, EventArgs e)
    {
        MessageBox.Show("ボタンがクリックされました!");
    }

    private void button2Click(object sender, EventArgs e)
    {
        MessageBox.Show("別のボタンがクリックされました!");
    }
}

このコードはシンプルですが、ボタンの数や操作が増えると、フォームのコードが複雑になりがちです。

ステップ2: 問題点を理解する

この設計には、以下の問題点があります:

  • コードの一貫性の欠如: 各ボタンの処理が分散しており、コードの一貫性が失われやすいです。
  • 保守性の低下: 新しい操作を追加するたびに、フォームのコードに新たなメソッドを追加しなければならず、コードが肥大化します。
  • 拡張性の問題: 操作を変更したい場合、フォームのコードに手を加える必要があり、変更が煩雑です。

Commandパターンの利点

Commandパターンを導入することで、次のような改善が期待できます:

  • クラスの責任を分離: 各操作を独立したクラスに分離し、フォームクラスが「どの操作を実行するか」だけを担当するようにします。
  • コードの集中化: 新しい操作を追加する際には、新しいコマンドクラスを作成するだけで済み、フォームのコード変更が不要になります。
  • 再利用性の向上: 操作ロジックが個別のクラスに集約されるため、他のコンテキストでも再利用可能です。

ステップ3: Commandパターンの基本を学ぶ

Commandパターンとは?

Commandパターンは、操作をオブジェクトとしてカプセル化し、操作の呼び出し元と処理を分離するデザインパターンです。

Commandパターンの構成

  1. インターフェース: 共通の動作を定義する ICommand インターフェースを作成します。
  2. 具体的なコマンドクラスICommand インターフェースを実装する具体的な操作クラスを作成します。
  3. インボーカー: 操作を実行するクラスを作成します。

ステップ4: Commandパターンを適用する

ICommandインターフェースを作成する

public interface ICommand
{
    void Execute();
}

具体的なコマンドクラスを別ファイルで作成する

// ShowMessageCommand.cs
public class ShowMessageCommand : ICommand
{
    private string message;

    public ShowMessageCommand(string message)
    {
        this.message = message;
    }

    public void Execute()
    {
        MessageBox.Show(message);
    }
}

Invokerクラスを作成する

public class ButtonInvoker
{
    private ICommand command;

    public void SetCommand(ICommand command)
    {
        this.command = command;
    }

    public void Invoke()
    {
        command.Execute();
    }
}

Form1クラスを更新する

public partial class Form1 : Form
{
    private ButtonInvoker invoker = new ButtonInvoker();

    public Form1()
    {
        InitializeComponent();
    }

    private void button1Click(object sender, EventArgs e)
    {
        invoker.SetCommand(new ShowMessageCommand("ボタン1がクリックされました!"));
        invoker.Invoke();
    }

    private void button2Click(object sender, EventArgs e)
    {
        invoker.SetCommand(new ShowMessageCommand("ボタン2がクリックされました!"));
        invoker.Invoke();
    }
}

ステップ5: 振り返りと応用

Commandパターンを導入することで、操作が増えた場合でも、新しいコマンドクラスを作成するだけで対応できます。また、Form1クラスのコードが非常にシンプルになり、他の動作にも応用が可能です。


このチュートリアルを通じて、シンプルな設計からデザインパターンを導入するプロセスを学び、より柔軟で拡張性のあるコードを書けるようになりましょう。