導入
振る舞いに関するパターンは「オブジェクト間の処理の受け渡し」を工夫します。Strategyは「アルゴリズムを差し替え可能にする」、Stateは「状態に応じて振る舞いを変える」。どちらも巨大なif/switchを、差し替え可能なオブジェクトに置き換えます。
図解
flowchart LR
C["コンテキスト"] --> S["Strategy(差し替え可能な処理)"]
S --> S1["通常料金"]
S --> S2["会員割引"]
S --> S3["セール価格"]
style S fill:#e1f5fe
サンプル
// Strategy: 料金計算アルゴリズムを外から差し替える
var cart = new Cart(new MemberDiscount());
Console.WriteLine(cart.Checkout(1000)); // 900
cart = new Cart(new NoDiscount());
Console.WriteLine(cart.Checkout(1000)); // 1000
interface IPricing { int Apply(int price); }
class NoDiscount : IPricing { public int Apply(int price) => price; }
class MemberDiscount : IPricing { public int Apply(int price) => price * 9 / 10; }
class Cart
{
private readonly IPricing _pricing;
public Cart(IPricing pricing) => _pricing = pricing;
public int Checkout(int price) => _pricing.Apply(price);
}
- Strategy: アルゴリズムをインターフェースにして、実行時に差し替える(前章のDIそのもの)
- State: オブジェクトの内部状態をクラス化し、状態ごとに振る舞いを変える(信号機・注文ステータス等)
- 巨大な条件分岐を「オブジェクトの差し替え」に変換するのが共通の狙い
演習
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です。