概要
Chain of Responsibility(責任の連鎖)パターンは、
複数のオブジェクトを連結し、要求を順に処理者に渡していくことで、柔軟な責任分散と処理制御を可能にする設計パターンである。
認証・バリデーション・エラーハンドリング・イベント処理など、順次処理を必要とする場面に最適。
1. なぜChain of Responsibilityが必要か?
❌ 全ての処理を一箇所にまとめると、責務が集中してしまう
def handle_request(request):
if is_valid(request):
if is_authenticated(request):
if is_authorized(request):
...
→ 処理フローがネストし、責務が密結合になる
✅ 責任を分割し、必要に応じて次のハンドラに委譲する
handler = AuthHandler(ValidationHandler(LoggingHandler()))
handler.handle(request)
→ 処理の連鎖が明示化され、柔軟なフロー制御が可能に
2. 基本構造
✅ Handler 抽象クラス
class Handler:
def __init__(self, next_handler=None):
self._next = next_handler
def handle(self, request):
raise NotImplementedError
def next(self, request):
if self._next:
self._next.handle(request)
✅ 具体的なハンドラ
class LoggingHandler(Handler):
def handle(self, request):
print(f"[LOG] リクエスト受信: {request}")
self.next(request)
class ValidationHandler(Handler):
def handle(self, request):
if not request.get("data"):
print("バリデーションエラー: data がありません")
return
self.next(request)
class AuthHandler(Handler):
def handle(self, request):
if request.get("auth") != "secret":
print("認証エラー: 認証トークンが無効です")
return
print("認証成功")
self.next(request)
✅ 使用例
chain = AuthHandler(ValidationHandler(LoggingHandler()))
req = {"auth": "secret", "data": "payload"}
chain.handle(req)
出力:
認証成功
[LOG] リクエスト受信: {'auth': 'secret', 'data': 'payload'}
3. Python的応用:関数型での実装も可能
def chain(*handlers):
def wrapped(request):
for handler in handlers:
if not handler(request):
break
return wrapped
def log_handler(request):
print(f"[LOG] {request}")
return True
def auth_handler(request):
if request.get("auth") == "ok":
return True
print("Auth failed")
return False
request_chain = chain(auth_handler, log_handler)
request_chain({"auth": "ok"})
→ 軽量なデコレーションベースで処理連鎖を構成可能
4. 実務ユースケース
✅ Webリクエストの中間処理(ミドルウェア)
→ 認証・ログ・バリデーションなどを処理チェーンとして分離
✅ イベントディスパッチャ(キーボード、UI入力)
→ 入力を優先順位付きに順次ハンドリング
✅ ログ処理(複数ハンドラで出力形式を切り替え)
→ コンソール → ファイル → リモート送信などの多段構成
✅ AIパイプラインやETLの処理段階制御
→ 入力 → 正規化 → 検証 → 推論 → 書き出しなどの連鎖的処理
5. よくある誤用と対策
❌ ハンドラが次の処理を呼び忘れて処理が止まる
→ ✅ next()の呼び出しルールを明確に設計し、ベースクラスで統一
❌ 状態の共有が難しい(各ハンドラが独立しすぎる)
→ ✅ 共通の context
や request
オブジェクトを共有する設計に
❌ 例外処理やフロー制御が入り乱れやすい
→ ✅ エラー時の中断やログ出力の責任を分離設計する
結語
Chain of Responsibility パターンとは、“責任の順序を構造で定義し、流れるように処理を受け渡す設計”である。
- 処理を段階的に分離し、動的な連鎖を可能にする
- 単一責任原則に従い、ハンドラの再利用・差し替えが容易
- Pythonではクラスでも関数でも、簡潔かつ拡張性のある実装が可能
Pythonicとは、“処理を柔らかく分けて、流れでつなげること”。
Chain of Responsibility パターンは、その柔軟性と秩序を、処理の連なりに刻む技法である。