概要
**ストラテジーパターン(Strategy Pattern)**は、
「あるアルゴリズムや処理の振る舞いを、動的に差し替え可能にする設計手法」である。
このパターンを使うことで、if-else
や switch
文による処理分岐を排除し、
オブジェクト指向の原則に基づいた、拡張に強い柔軟な構造を構築できる。
本稿では、Pythonでの実装方法と、現場で活かせるパターン適用の実務例を紹介する。
1. なぜストラテジーが必要か?
❌ 条件分岐による処理切替
if payment_type == "credit":
process_credit(payment)
elif payment_type == "paypal":
process_paypal(payment)
→ 新しい支払い手段を追加するたびに、条件分岐が膨張し保守性が低下
2. ストラテジーパターンの基本構造
✅ 共通のインタフェース
class PaymentStrategy:
def pay(self, amount):
raise NotImplementedError
✅ 具象戦略クラス
class CreditCardPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paid {amount} via Credit Card")
class PayPalPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paid {amount} via PayPal")
✅ コンテキスト(呼び出し側)
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self.strategy = strategy
def process(self, amount):
self.strategy.pay(amount)
✅ 実行例
processor = PaymentProcessor(PayPalPayment())
processor.process(1000)
3. 動的切り替えの実装と利点
strategy_map = {
"credit": CreditCardPayment(),
"paypal": PayPalPayment(),
# 他の戦略も追加可能
}
def get_processor(method):
return PaymentProcessor(strategy_map[method])
- 条件分岐を排除
- 拡張時に既存コードを変更しない(OCPの実現)
- 戦略のテストや切り替えが容易
4. 実務ユースケース
✅ 並列アルゴリズムの切り替え
class SortStrategy:
def sort(self, data): ...
class QuickSort(SortStrategy):
def sort(self, data): return sorted(data)
class BubbleSort(SortStrategy):
def sort(self, data):
# 実装略
return data
✅ データ出力形式の動的切り替え
class ExportStrategy:
def export(self, data): ...
class CSVExporter(ExportStrategy):
def export(self, data): print("Exporting as CSV")
class JSONExporter(ExportStrategy):
def export(self, data): print("Exporting as JSON")
5. Pythonならではの実装スタイル:関数戦略
✅ 戦略をクラスではなく関数で表現
def credit_strategy(amount):
print(f"Credit: {amount}")
def paypal_strategy(amount):
print(f"PayPal: {amount}")
def process_payment(strategy, amount):
strategy(amount)
→ 軽量かつ関数型志向な設計も可能
→ 小規模・一時的な切り替えに有効
6. よくある誤用と対策
❌ インタフェースを定義せず共通性が破綻
→ ✅ Strategy
インタフェース(抽象基底クラス or プロトコル)を定義すべき
❌ コンテキスト側が戦略の中身を知ってしまう
→ ✅ コンテキストは strategy.pay()
のように抽象的に操作するべき
結語
ストラテジーパターンは、「振る舞いを切り替えられる構造を、構文ではなく設計で実現する」ための手法である。
- 分岐を排除し、拡張に強いアーキテクチャを構築
- 戦略ごとのコードを明示的に分離し、単体テストしやすくする
- 関数ベース・クラスベース・DIコンテナと組み合わせた多様な設計が可能
Pythonicとは、“制御の流れすらオブジェクトとして管理する”ことであり、
ストラテジーパターンはその意図を、構造として洗練する強力な手段である。