本文へスキップ
BecomeCoder

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

振る舞い①:Strategy / State

ブラウザで完結

導入

振る舞いに関するパターンは「オブジェクト間の処理の受け渡し」を工夫します。Strategyは「アルゴリズムを差し替え可能にする」、Stateは「状態に応じて振る舞いを変える」。どちらも巨大なif/switchを、差し替え可能なオブジェクトに置き換えます。

図解

flowchart LR
    C["コンテキスト"] --> S["Strategy(差し替え可能な処理)"]
    S --> S1["通常料金"]
    S --> S2["会員割引"]
    S --> S3["セール価格"]
    style S fill:#e1f5fe

サンプル

Strategyは「アルゴリズム1つ=クラス1つ=ファイル1つ」。料金ルールが増えるほど、この分け方のありがたみが出ます。

1. アルゴリズムの共通の形(IPricing.cs)。

public interface IPricing
{
    int Apply(int price);
}

2. 個々のアルゴリズム(NoDiscount.cs / MemberDiscount.cs)。「セール価格」を足したくなったら、ここにファイルを1つ増やすだけです。

public class NoDiscount : IPricing
{
    public int Apply(int price) => price;
}
public class MemberDiscount : IPricing
{
    public int Apply(int price) => price * 9 / 10;
}

3. 戦略を使う側(Cart.cs)。Cartは割引の中身を一切知りません。だから割引が増えてもこのファイルは変わりません。

// Strategy: 料金計算アルゴリズムを外から受け取って差し替える
public class Cart
{
    private readonly IPricing _pricing;
    public Cart(IPricing pricing) => _pricing = pricing;
    public int Checkout(int price) => _pricing.Apply(price);
}

4. 組み立てる側(Program.cs)。どの戦略を使うかを決めるのは、ここだけです。

var cart = new Cart(new MemberDiscount());
Console.WriteLine(cart.Checkout(1000));   // 900

cart = new Cart(new NoDiscount());
Console.WriteLine(cart.Checkout(1000));   // 1000
  • Strategy: アルゴリズムをインターフェースにして、実行時に差し替える(前章のDIそのもの)
  • State: オブジェクトの内部状態をクラス化し、状態ごとに振る舞いを変える(信号機・注文ステータス等)
  • 巨大な条件分岐を「オブジェクトの差し替え」に変換するのが共通の狙い
  • ifだらけの1ファイルではなく、ルールごとの小さなファイルに分かれるので差分が読みやすい

演習

var calc = new Calculator(new AddStrategy());
Console.WriteLine(calc.Run(3, 4));   // 7

// TODO: IOperation(Do(int,int)→int)を実装する AddStrategy(加算)を定義してください
interface IOperation { int Do(int a, int b); }
class Calculator
{
    private readonly IOperation _op;
    public Calculator(IOperation op) => _op = op;
    public int Run(int a, int b) => _op.Do(a, b);
}
___
  • 期待される出力: 7
ヒント1を見る

class AddStrategy : IOperation { public int Do(int a, int b) => a + b; }

ヒント2を見る

戦略を差し替えればCalculator本体は無変更で動作が変わります

まとめ

  • Strategyはアルゴリズムを差し替え可能にする
  • Stateは状態ごとに振る舞いを切り替える
  • 巨大な条件分岐をオブジェクトの差し替えに置き換える

次回: 通知と仲介のObserver/Mediatorです。

実際に動かしてみよう

このレッスンのサンプルは、実務と同じように役割ごとの .cs ファイルへ分けてあります。下のエディタは最初からその複数ファイルが入った状態で、上のタブでファイルを切り替えられます。そのまま「▶ 実行」を押せば全ファイルをまとめてコンパイルして動かせるので、クラスを足したりファイルをまたいで書き換えたりしながら進めましょう(演習は本文のコードをコピーして Program.cs のタブに貼り付ければ試せます)。

C# — ブラウザ内で実行

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

次のレッスンへ →