概要
Strategy(ストラテジー)パターンは、
ある処理の具体的なアルゴリズムをクラスとして切り出し、実行時に動的に選択・切り替え可能な構造を提供するパターンである。
アルゴリズムが複数存在する場合でも、分岐や条件に依存せず、疎結合かつ柔軟に設計できる。
1. なぜStrategyが必要か?
❌ アルゴリズムの分岐がコード中にべた書きされる
if method == "bubble":
sort_bubble(data)
elif method == "quick":
sort_quick(data)
→ アルゴリズム追加のたびに条件分岐が肥大化し、保守性が低下
✅ アルゴリズムをクラス化し、戦略として注入
context = SortContext(QuickSortStrategy())
context.sort(data)
→ 選択と実行を分離し、柔軟な戦略切り替えを実現
2. 基本構造
✅ Strategyインターフェース
class SortStrategy:
def sort(self, data):
raise NotImplementedError
✅ ConcreteStrategy(具体的アルゴリズム)
class BubbleSortStrategy(SortStrategy):
def sort(self, data):
print("バブルソート実行")
return sorted(data) # 実装省略(例)
class QuickSortStrategy(SortStrategy):
def sort(self, data):
print("クイックソート実行")
return sorted(data) # 実装省略(例)
✅ Context(アルゴリズムの使用者)
class SortContext:
def __init__(self, strategy: SortStrategy):
self._strategy = strategy
def set_strategy(self, strategy: SortStrategy):
self._strategy = strategy
def sort(self, data):
return self._strategy.sort(data)
✅ 使用例
data = [5, 3, 8, 2]
context = SortContext(BubbleSortStrategy())
context.sort(data)
context.set_strategy(QuickSortStrategy())
context.sort(data)
出力:
バブルソート実行
クイックソート実行
3. Python的応用:関数を戦略として扱う
class SortContext:
def __init__(self, strategy_func):
self._strategy = strategy_func
def set_strategy(self, strategy_func):
self._strategy = strategy_func
def sort(self, data):
return self._strategy(data)
def merge_sort(data):
print("マージソート実行")
return sorted(data)
context = SortContext(merge_sort)
context.sort([9, 1, 4])
→ 関数やラムダ式をそのまま戦略として注入可能
4. 実務ユースケース
✅ ソートアルゴリズム・暗号化方式・圧縮方式などの切り替え
→ 各戦略をモジュール化して選択可能に
✅ 支払い戦略(クレジット/PayPay/現金)などの決済処理
→ UIや状況に応じて戦略的に実装切り替え
✅ ログ出力形式(テキスト/JSON/構造化ログ)
→ フォーマッターを切り替えて再利用
✅ 検索エンジンでのマッチング戦略(完全一致/部分一致/あいまい)
→ ユーザーの意図に応じてアルゴリズムを切り替え可能に
5. よくある誤用と対策
❌ コンテキストクラスにロジックを持たせすぎる
→ ✅ 処理はすべてStrategy側に委譲し、Contextは切り替えだけを担う
❌ Strategyが実質的に共通コードを大量に持つ
→ ✅ 共通処理はBaseStrategyにまとめる or Mixin設計で分離
❌ Strategyを使うほどの選択肢がない場面での濫用
→ ✅ 明確に切り替える必要がある処理にのみ適用する
結語
Strategyパターンとは、“振る舞いをアルゴリズムとして独立させ、状況に応じて動的に切り替える柔軟な設計手法”である。
- 条件分岐を排除し、アルゴリズムの切り替えを構造で制御
- 動的な選択・組み替えを可能にし、テスト・拡張・再利用性を向上
- Pythonでは関数やクラスを柔軟に戦略として扱え、軽量かつ明快にStrategyを実装できる
Pythonicとは、“選択を構造として設計に取り込むこと”。
Strategyパターンはその選択の自由を、アルゴリズムのレベルで美しく表現する構造技法である。