Pythonで実装するChain of Responsibilityパターン：責任の流れを直列に構成する



## 概要

**Chain of Responsibility（責任の連鎖）パターン**は、  
複数の処理者（ハンドラ）を**直列に構成し、要求を順に委譲していく設計パターン**である。

各ハンドラは「自分が処理できるかどうか」を判断し、処理できなければ**次のハンドラにバトンを渡す**。これにより、**処理フローの柔軟な拡張とカプセル化が可能**になる。

---

## 1. なぜChain of Responsibilityが必要か？

### ❌ 条件分岐で処理ルートを管理するとメンテナンスが困難に

```python
def handle(request):
    if request == "auth":
        ...
    elif request == "log":
        ...
    elif request == "cache":
        ...
```

→ **条件が増えるたびにif/elifが複雑化していく**

---

### ✅ 各処理をオブジェクトに分離し、責任の流れを構成する

```python
auth.set_next(logger).set_next(cacher)
auth.handle("log")
```

→ **処理を柔軟に組み換え可能で、単一責任原則も維持できる**

---

## 2. 基本構造

### ✅ Handlerインターフェース

```python
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（具体的な処理者）

```python
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)
```

---

### ✅ 使用例

```python
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的応用：デコレータやミドルウェアとしての連鎖設計

```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パターンはその責任の知性を、設計の流動性として昇華する技法である。**