概要
Strategy(ストラテジー)パターンは、
アルゴリズムや処理手順をオブジェクトとしてカプセル化し、実行時に自由に切り替えられるようにする設計パターンである。
条件分岐を排除しつつ、動作の切り替えや拡張を柔軟に行いたいときに有効。
ソート手法、認証方法、価格計算、ログ戦略などに応用できる。
1. なぜStrategyが必要か?
❌ if/elseで処理パターンを切り替える設計はスケーラビリティに乏しい
if method == "credit":
pay_credit()
elif method == "paypal":
pay_paypal()
→ 選択肢が増えるほど条件分岐が複雑化
✅ Strategyに切り出すことで構造的に拡張可能に
strategy = PayPalStrategy()
payment.set_strategy(strategy)
payment.process()
→ アルゴリズム切替がクラス設計に組み込まれる
2. 基本構造
✅ Strategyインターフェース
class PaymentStrategy:
def pay(self, amount):
raise NotImplementedError
✅ Concrete Strategy(実装)
class CreditCardStrategy(PaymentStrategy):
def pay(self, amount):
print(f"クレジットカードで {amount} 円支払い")
class PayPalStrategy(PaymentStrategy):
def pay(self, amount):
print(f"PayPalで {amount} 円支払い")
✅ Context(戦略を使う側)
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self._strategy = strategy
def set_strategy(self, strategy: PaymentStrategy):
self._strategy = strategy
def process(self, amount):
self._strategy.pay(amount)
✅ 使用例
processor = PaymentProcessor(CreditCardStrategy())
processor.process(5000)
processor.set_strategy(PayPalStrategy())
processor.process(5000)
出力:
クレジットカードで 5000 円支払い
PayPalで 5000 円支払い
3. Python的応用:関数ベースのストラテジー設計
def credit_pay(amount):
print(f"[関数] クレジットで {amount} 円")
def paypal_pay(amount):
print(f"[関数] PayPalで {amount} 円")
class PaymentProcessor:
def __init__(self, strategy):
self.strategy = strategy
def process(self, amount):
self.strategy(amount)
processor = PaymentProcessor(credit_pay)
processor.process(3000)
processor.strategy = paypal_pay
processor.process(3000)
→ 関数もStrategyとして機能できるのがPythonの強み
4. 実務ユースケース
✅ 支払い、ログ出力、認証などの方式切替
→ 特定処理を柔軟に差し替え可能にする構造
✅ データの変換・圧縮アルゴリズムの差し替え
→ 同じインターフェースで異なる処理戦略を適用
✅ システム構成に応じた動的な挙動制御
→ ローカル/クラウド、テスト/本番で戦略を差し替え
✅ 機械学習における予測モデルの統一インターフェース
→ モデルA, B, Cを同一戦略構造で扱い、切替可能に設計
5. よくある誤用と対策
❌ Contextクラスに戦略が固定実装されている
→ ✅ 戦略はContextの外部から注入できる構造にする
❌ Strategyの責務があいまいで肥大化する
→ ✅ 1戦略 = 1アルゴリズム に限定してSRPを守る
❌ Strategyの切り替えが実行中に許されない設計
→ ✅ set_strategy()など明示的切替用メソッドを提供
結語
Strategyパターンとは、“やり方の違いを構造で受け入れ、選択可能にする設計”である。
- アルゴリズムをオブジェクト化し、選択・拡張・切替を柔軟に可能に
- 条件分岐を排除して、開放/閉鎖原則に従ったスケーラブルなコードを実現
- Pythonでは関数・クラスの両スタイルで実装でき、場面に応じた選択が可能
Pythonicとは、“処理の違いを柔らかく切り出し、選べるようにすること”。
Strategyパターンはその柔軟さを、選択可能な知性として設計に宿す技法である。