本文へスキップ
BecomeCoder

C#デザインパターンコース · 第1章 デザインパターン · レッスン10

振る舞い③:Command / Chain of Responsibility

ブラウザで完結

導入

Commandは「操作をオブジェクトとして表現」——実行・取り消し・キュー化ができるように。Chain of Responsibilityは「処理役を数珠つなぎにし、扱える者が処理」——承認フローやミドルウェアの構造です。

図解

flowchart LR
    R["要求"] --> H1["担当A<br/>扱える?"]
    H1 -->|無理| H2["担当B<br/>扱える?"]
    H2 -->|無理| H3["担当C<br/>処理"]

サンプル

// Command: 操作をオブジェクト化して、あとでまとめて実行
var history = new List<ICommand>
{
    new PrintCommand("A"),
    new PrintCommand("B"),
};
foreach (var cmd in history) cmd.Execute();   // 実行: A / 実行: B

// Chain of Responsibility: 承認額に応じて担当者を数珠つなぎで探す
var chain = new Leader(new Manager(null));
chain.Approve(80000);    // 課長が承認: 80000円
chain.Approve(300000);   // 部長が承認: 300000円

interface ICommand { void Execute(); }
class PrintCommand : ICommand
{
    private readonly string _label;
    public PrintCommand(string label) => _label = label;
    public void Execute() => Console.WriteLine($"実行: {_label}");
}

abstract class Approver
{
    protected Approver? Next;
    protected Approver(Approver? next) => Next = next;
    public abstract void Approve(int amount);
}
class Leader : Approver
{
    public Leader(Approver? next) : base(next) { }
    public override void Approve(int amount)
    {
        if (amount <= 100000) Console.WriteLine($"課長が承認: {amount}円");
        else Next?.Approve(amount);   // 扱えなければ次へ回す
    }
}
class Manager : Approver
{
    public Manager(Approver? next) : base(next) { }
    public override void Approve(int amount) => Console.WriteLine($"部長が承認: {amount}円");
}
  • Command: 操作をExecute()を持つオブジェクトにし、履歴・キュー・取り消しに対応できる
  • Chain of Responsibility: 処理役を連結し、「自分が扱えなければ次へ回す」
  • どちらも「呼び出し側」と「処理内容」を切り離す

演習

ICommand cmd = new GreetCommand("Taro");
cmd.Execute();   // こんにちは、Taro

// TODO: Execute() で "こんにちは、名前" を出力する GreetCommand を定義してください
interface ICommand { void Execute(); }
___
  • 期待される出力: こんにちは、Taro
ヒント1を見る

名前をフィールドに持ち、Executeで出力します

ヒント2を見る

class GreetCommand : ICommand { private readonly string _name; public GreetCommand(string name) => _name = name; public void Execute() => Console.WriteLine($"こんにちは、{_name}"); }

まとめ

  • Commandは操作をオブジェクト化し、実行・履歴・取り消しを可能にする
  • Chain of Responsibilityは処理役を連結し順に委ねる
  • どちらも呼び出しと処理内容を分離する

次回: 手順の骨組みと反復のTemplate Method/Iteratorです。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。