概要
Chain of Responsibility(責任の連鎖)パターンは、
処理の責任を複数のオブジェクト間でリレー形式に渡しながら分散させる設計パターンである。
各処理単位は自身で対応できるかを判断し、できなければ次に委譲。
この構造により、送信者は具体的な処理担当者を知ることなく処理を依頼できる。
1. なぜChain of Responsibilityが必要か?
❌ 処理の分岐が呼び出し元に集中し、密結合かつ拡張性が低い
if req.type == "auth":
handle_auth(req)
elif req.type == "log":
handle_log(req)
→ 条件が増えるたびにコードが膨張し、変更に弱くなる
✅ 各責任を持つハンドラに分け、処理を順番に委譲していく構造へ
handler1.set_next(handler2).set_next(handler3)
handler1.handle(req)
→ 処理の流れを動的に構築可能かつ、責任の局所化が実現できる
2. 基本構造
✅ Handler(共通インターフェース)
class Handler:
def set_next(self, handler):
self._next = handler
return handler
def handle(self, request):
if hasattr(self, '_next'):
return self._next.handle(request)
return None
✅ ConcreteHandlers(具体的な責任を持つクラス)
class AuthHandler(Handler):
def handle(self, request):
if request == "auth":
print("[AuthHandler] 認証処理を実行")
return True
return super().handle(request)
class LogHandler(Handler):
def handle(self, request):
if request == "log":
print("[LogHandler] ログ記録処理を実行")
return True
return super().handle(request)
class FallbackHandler(Handler):
def handle(self, request):
print(f"[FallbackHandler] 未対応のリクエスト: {request}")
return False
✅ 使用例
auth = AuthHandler()
log = LogHandler()
fallback = FallbackHandler()
auth.set_next(log).set_next(fallback)
auth.handle("auth") # [AuthHandler] 認証処理を実行
auth.handle("log") # [LogHandler] ログ記録処理を実行
auth.handle("unknown") # [FallbackHandler] 未対応のリクエスト: unknown
3. Python的応用:関数型での簡易実装
def chain(*handlers):
def handle(request):
for handler in handlers:
if handler(request):
return True
print("すべてのハンドラがリクエストを処理できませんでした")
return False
return handle
def auth_handler(req): return req == "auth" and print("auth済み")
def log_handler(req): return req == "log" and print("ログ処理")
handle = chain(auth_handler, log_handler)
handle("auth")
handle("log")
handle("other")
→ 関数の連鎖でも同様の構造が可能。軽量な場合に有効
4. 実務ユースケース
✅ リクエスト処理パイプライン(Web/Middleware)
→ 認証 → バリデーション → ログ → 処理
✅ 入力検証の段階処理
→ 入力値を条件ごとに順番に検証・エラーハンドリング
✅ イベントハンドラの委譲処理
→ 複数のレイヤーでイベント処理を試み、最終的に対応者に届く
✅ 通知やアラートの優先ルーティング
→ 通知条件に応じたハンドラの選定・実行
5. よくある誤用と対策
❌ ハンドラ同士が互いを知りすぎている(tight coupling)
→ ✅ set_next で明示的に構築し、内部には依存させない
❌ チェーンの構築を分散して行い、追跡不可能に
→ ✅ チェーン構築は集中管理し、処理の流れが明示的に分かるようにする
❌ 各ハンドラが責任範囲を曖昧に処理し始める
→ ✅ それぞれが何を処理するのかを明確に定義する
結語
Chain of Responsibilityパターンとは、“責任を分けて、順に流しながら柔軟に処理する設計”である。
- 各処理単位が自律し、順番に委譲される構造で柔軟な処理フローを実現
- 新たな責任の追加や並び替えが容易で、動的な処理チェーンの構築に最適
- Pythonではクラス・関数の両方で実装可能で、明快かつ表現力豊かな設計ができる
Pythonicとは、“誰が処理するかではなく、誰が処理できるかで構造を設計すること”。
Chain of Responsibilityパターンはその責任の知性を、処理の連続性として表現する技法である。