概要
Chain of Responsibility(責任の連鎖)パターンは、
複数の処理者(ハンドラ)を直列に構成し、要求を順に委譲していく設計パターンである。
各ハンドラは「自分が処理できるかどうか」を判断し、処理できなければ次のハンドラにバトンを渡す。これにより、処理フローの柔軟な拡張とカプセル化が可能になる。
1. なぜChain of Responsibilityが必要か?
❌ 条件分岐で処理ルートを管理するとメンテナンスが困難に
def handle(request):
if request == "auth":
...
elif request == "log":
...
elif request == "cache":
...
→ 条件が増えるたびにif/elifが複雑化していく
✅ 各処理をオブジェクトに分離し、責任の流れを構成する
auth.set_next(logger).set_next(cacher)
auth.handle("log")
→ 処理を柔軟に組み換え可能で、単一責任原則も維持できる
2. 基本構造
✅ Handlerインターフェース
class Handler:
def set_next(self, handler):
self._next_handler = handler
return handler
def handle(self, request):
if self._next_handler:
return self._next_handler.handle(request)
return None
✅ ConcreteHandler(具体的な処理者)
class AuthHandler(Handler):
def handle(self, request):
if request == "auth":
print("認証処理を実行")
else:
super().handle(request)
class LogHandler(Handler):
def handle(self, request):
if request == "log":
print("ログ記録処理を実行")
else:
super().handle(request)
class CacheHandler(Handler):
def handle(self, request):
if request == "cache":
print("キャッシュ処理を実行")
else:
super().handle(request)
✅ 使用例
auth = AuthHandler()
logger = LogHandler()
cache = CacheHandler()
auth.set_next(logger).set_next(cache)
auth.handle("auth") # → 認証処理
auth.handle("log") # → ログ記録処理
auth.handle("cache") # → キャッシュ処理
auth.handle("other") # → 誰も処理しない
出力:
認証処理を実行
ログ記録処理を実行
キャッシュ処理を実行
3. Python的応用:デコレータやミドルウェアとしての連鎖設計
def middleware1(req, nxt): print("M1"); nxt(req)
def middleware2(req, nxt): print("M2"); nxt(req)
def middleware3(req, nxt): print("M3"); nxt(req)
def chain(middlewares, final):
def execute(req):
def call(index):
if index < len(middlewares):
middlewares[index](req, lambda r: call(index + 1))
else:
final(r)
call(0)
return execute
runner = chain([middleware1, middleware2, middleware3], lambda r: print("完了"))
runner("リクエスト")
→ ミドルウェアやイベントパイプラインにも応用可能
4. 実務ユースケース
✅ HTTPリクエスト処理のミドルウェア(Django / Flask)
→ 認証 → ログ → キャッシュ → バリデーション の流れを構成可能
✅ ロギング処理の段階的適用(標準出力→ファイル→ネットワーク)
→ ログレベルに応じて適切なハンドラに分岐
✅ 入力バリデーションのルールチェーン
→ 順に検証を行い、失敗時に即中断、成功時は次へ
✅ セキュリティチェック、フィルタリング、サニタイジング
→ 責任の分担によって、処理の独立性を保つ
5. よくある誤用と対策
❌ ハンドラが1つで全ての責任を背負ってしまう
→ ✅ ハンドラごとの単一責任を守る
❌ チェーン構成が静的で柔軟に変えられない
→ ✅ 実行時に組み替えられるようset_nextを提供する
❌ ハンドラが処理を流すかどうかを忘れて止まる
→ ✅ super().handle()
を必ず呼ぶ構造を意識的に設計
結語
Chain of Responsibilityパターンとは、“責任の流れを構造化することで、処理を動的かつ柔軟に委譲する設計”である。
- 各処理をモジュール化し、連鎖することで柔軟なフローを構成
- 責任の範囲と処理順を分離し、保守性と拡張性を高める
- Pythonではクラス連結・関数チェーン・ミドルウェア構造に自然に適用可能
Pythonicとは、“処理の責任を持ちすぎず、次に委ねること”。
Chain of Responsibilityパターンはその責任の知性を、設計の流動性として昇華する技法である。