概要
Strategy(ストラテジー)パターンは、
ある機能に対して複数の異なるアルゴリズムが存在する場合に、
その選択・切り替えを動的かつ柔軟に行えるように設計する構造的パターンである。
アルゴリズムの実装をインターフェースの背後に隠蔽することで、
拡張可能で変更に強い設計を実現する。
1. なぜStrategyが必要か?
❌ 条件分岐でアルゴリズムを切り替える設計
def calculate(a, b, method="add"):
if method == "add":
return a + b
elif method == "sub":
return a - b
→ 新しい戦略が増えるたびに関数を改修する必要があり、拡張性が低い
✅ 戦略(アルゴリズム)を分離し、切り替え可能に
calc = Calculator(AddStrategy())
calc.execute(10, 5) # → 15
→ アルゴリズムを動的に切り替えられる柔軟な設計へ
2. 基本構造
✅ Strategyインターフェース
class Strategy:
def execute(self, a, b):
raise NotImplementedError
✅ 具体的戦略クラス
class AddStrategy(Strategy):
def execute(self, a, b):
return a + b
class SubtractStrategy(Strategy):
def execute(self, a, b):
return a - b
class MultiplyStrategy(Strategy):
def execute(self, a, b):
return a * b
✅ コンテキストクラス
class Calculator:
def __init__(self, strategy: Strategy):
self._strategy = strategy
def set_strategy(self, strategy: Strategy):
self._strategy = strategy
def execute(self, a, b):
return self._strategy.execute(a, b)
✅ 使用例
calc = Calculator(AddStrategy())
print(calc.execute(4, 2)) # 6
calc.set_strategy(SubtractStrategy())
print(calc.execute(4, 2)) # 2
calc.set_strategy(MultiplyStrategy())
print(calc.execute(4, 2)) # 8
3. Python的応用:関数ベースの戦略実装
def divide(a, b):
return a / b
class FunctionStrategy(Strategy):
def __init__(self, func):
self.func = func
def execute(self, a, b):
return self.func(a, b)
calc.set_strategy(FunctionStrategy(divide))
print(calc.execute(10, 2)) # 5.0
→ 関数やラムダでも簡易的に戦略を定義可能
4. 実務ユースケース
✅ 並び替え・フィルタリングロジックの切替
→ 名前順、日付順、優先度順など動的に適用ロジックを切替可能
✅ 認証方式の切替(パスワード / トークン / OAuth)
→ Strategyでログイン方式を切り替え、統一された呼び出し口を維持
✅ レコメンド・評価ロジックのバリエーション設計
→ 機械学習スコア / 手動重み付け / 人気順 などの計算戦略を柔軟に追加
✅ 戦略テストやA/Bテストの適用
→ 実行時に戦略を差し替えることで仮説検証を柔軟に行える
5. よくある誤用と対策
❌ Strategy内に状態や副作用を持たせる
→ ✅ 戦略はあくまで「計算・振る舞い」に特化し、副作用は避ける
❌ Contextが特定のStrategy型を直接呼ぶ
→ ✅ execute()
を通じてポリモーフィズムで切り替えること
❌ StrategyとFactoryの混同
→ ✅ Strategyは切り替えるための抽象化であり、生成責務はFactoryへ分離
結語
Strategyパターンとは、“アルゴリズムの選択可能性を設計段階で保証する”柔軟な構造手法である。
- 条件分岐から解放され、オープン/クローズドの原則を自然に満たす
- 戦略のテスト、切替、差し替えが簡易で、仮説検証やA/Bテストの足場として強力
- Pythonの関数型構文・クラス設計の両方と親和性が高く、現実的な設計に適している
Pythonicとは、“振る舞いを注入可能な形で設計する”ことであり、
Strategyパターンはその注入の自由度を高め、コードを柔らかく保つための知的な手段である。