gof-strategy について
複数のアルゴリズムから選ぶ開発者向けに、Strategyパターンを解説するスキルです。共通インターフェースで振る舞いを隠蔽する方法と、その間接化が不要な場合を扱います。
主な機能
- 01複数アルゴリズムのカプセル化
- 02インターフェースによる振る舞いの委譲
- 03実行時のストラテジー切り替え
- 04関連パターンとの比較
活用シーン
- 01型によるアルゴリズム分岐の置き換え
- 02サブクラスの増殖を避けた振る舞いの変更
- 03明確な必要性に基づく第2のアルゴリズム追加
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill gof-strategyインストール後、Claude Code で/gof-strategyを入力して読み込まれたか確認します。
詳細
1 行の概要
アルゴリズムのファミリーに属する各アルゴリズムを共通インターフェースの背後に隠し、アルゴリズムをハードコードしたり型フラグに応じて分岐したりする代わりに、クライアントが実行時に必要なものを組み合わせられるようにします。
このスキルを使用する場面
- クラスに、代替アルゴリズム(ソート順、価格ルール、検証方式など)を選択する「type」フィールドに基づく分岐
switch/ifがある。 - 1 つの振る舞いを変えるためにサブクラス化を使った結果、クラスが組み合わせ爆発を起こしている。
- アルゴリズムの種類が今後増える見込みがある。
- 2 つのクラスが振る舞いの大部分を共有しているものの、1 つの要素だけが異なる(例:
MallardDuckとRubberDuckは鳴き方と飛び方だけが異なる)。
このスキルを使用しない場面
- アルゴリズムが 1 つしかなく、2 つ目も見込まれない場合。間接化を加えるのは YAGNI です。
- 変化する振る舞いが、ほぼ同一の構造を持つ一連のステップに関係する場合。それは
gof-template-methodです。 - 変化するのが「どのように計算するか」ではなく、「何を組み合わせるか」である場合。それは多くの場合
gof-decoratorです。
コアコンテンツ
Strategy は、クライアントが行うこと と その方法 を切り離します。クライアントは小さなインターフェースを介して Strategy オブジェクトへの参照を保持し、具象 Strategy は生成時に組み込まれます(または、実行時に変更するためにセッターを通じて設定されます)。
継承よりコンポジションを優先します。1 つのメソッドを変えるためにサブクラス化する代わりに、そのメソッドを担う小さなオブジェクトを注入します。各 Strategy は独立してテストでき、ホストに触れずに差し替えられます。
擬似的な形:
- インターフェース
Strategy { operate(input) }を定義します。 - 具象 Strategy はこれを実装します:
StrategyA、StrategyB、… - コンテキストクラスは
Strategyを保持し、処理を委譲します:context.do(input) { strategy.operate(input) }。
判断のヒント
- 現時点で実際に 2 つ以上のアルゴリズムがある場合、または今は 1 つでも、近いうちに 2 つ目が必要となる強い理由がある場合に適用します。
- アルゴリズムごとのサブクラスが爆発的に増えるのを避けるには、Strategy を優先します。
- Strategy がステートレスなら、コンテキストごとに割り当てる代わりに
objectインスタンス(シングルトン)にできます。
アンチパターン
- 「後で必要になるかもしれない」という理由で、アルゴリズムが 1 つしかないのに Strategy を導入すること。間接化のコストはすぐに発生しますが、そのメリットは実現しない可能性があります。
- 状態を持ちすぎる Strategy オブジェクト。Strategy は 振る舞い を担うものです。Strategy が呼び出しごとに大量の状態を持つ場合は、境界を見直してください。
- Strategy の名前を、ドメイン上の 意味(
PriorityFirstSort、ChronologicalSort)ではなく、実装の 方法(FastSortStrategy、SlowSortStrategy)に基づけること。
関連項目
gof-state— 構造は同じですが、意図が異なります(Strategy は計算する内容を変え、State はオブジェクトのライフサイクルに応じて振る舞いを変えます)。gof-template-method— 変化するのがアルゴリズム全体ではなく、アルゴリズム内のステップ である場合に使用します。gof-command— アルゴリズムではなく操作をパラメーター化する場合に使用します。gof-kotlin-idioms— Kotlin では、Strategy は多くの場合、関数型パラメーター(T) -> Rにすぎません。インターフェースは不要です。
参考資料
- Head First Design Patterns(第 2 版)、第 1 章(「Welcome to Design Patterns」)— Duck シミュレーターの例を用いて説明する、Strategy の代表的な章です。
コメント
Markdown 対応