2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで構築するChain of Responsibilityパターン:責任の流れを設計する柔軟な分岐構造

Posted at

概要

Chain of Responsibility(責任の連鎖)パターンは、
リクエストを複数の処理者(ハンドラ)に順番に渡し、
それぞれの処理者が「自分が処理可能かどうか」を判断しながら責任を委譲する設計パターンである。

この構造により、if-else や switch-case で構成された巨大な分岐処理を疎結合で柔軟な連鎖構造に変換できる。


1. なぜChain of Responsibilityが必要か?

❌ 巨大なif-elseブロックによる分岐処理

def handle(request):
    if request == "A":
        ...
    elif request == "B":
        ...
    elif request == "C":
        ...

処理の追加・変更が困難で、責務が集中した構造


✅ 各処理者をクラスに分割し、連鎖構造で責任を委譲

handler_a.set_next(handler_b).set_next(handler_c)
handler_a.handle(request)

柔軟かつ拡張可能な設計に進化


2. 基本構造

✅ 抽象ハンドラクラス

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

✅ 具体的な処理者クラス

class AuthHandler(Handler):
    def handle(self, request):
        if request.get("auth"):
            print("認証OK")
            return super().handle(request)
        else:
            print("認証失敗")
            return "Unauthorized"

class DataHandler(Handler):
    def handle(self, request):
        if "data" in request:
            print("データ処理中...")
            return "Success"
        return super().handle(request)

✅ 使用例

auth = AuthHandler()
data = DataHandler()

auth.set_next(data)

request = {"auth": True, "data": "payload"}
result = auth.handle(request)
print(result)  # → Success

3. Python的応用:関数やラムダで構築するチェーン

class FunctionHandler(Handler):
    def __init__(self, func):
        self.func = func
        self._next = None

    def handle(self, request):
        if self.func(request):
            return super().handle(request)
        return "Blocked"
h1 = FunctionHandler(lambda r: r.get("step1"))
h2 = FunctionHandler(lambda r: r.get("step2"))
h1.set_next(h2)
h1.handle({"step1": True, "step2": True})

4. 実務ユースケース

✅ リクエスト処理パイプライン(Webミドルウェア)

→ 認証 → バリデーション → ログ → 本処理 … のような前処理構成に最適


✅ フォールバック付き処理系(プランA → プランB → プランC)

→ 最初に成功した処理で止めたいケースに有効


✅ イベントディスパッチャ、ルーティングの定義

→ 各ハンドラに処理条件をもたせ、該当するものが責任を引き受ける


✅ エラーハンドリング・再試行フロー

→ 失敗時の処理チェーン、代替処理の定義が可能


5. よくある誤用と対策

❌ 全てのハンドラが必ず処理を行う構造

→ ✅ handle()処理済みかどうかの判定を明確に実装し、必要に応じて打ち切る


❌ チェーンの順番が意図とずれる

→ ✅ set_next() の順序に依存するため、構築時に明示的に順番を定義


❌ ステートレス処理とステートフル処理の混在

→ ✅ 各ハンドラの設計において、副作用の有無を意識的に区別


結語

Chain of Responsibilityパターンとは、“責任を分散させながら柔軟に制御するための構造”である。

  • 処理の流れを構造で記述し、責務の分離と順序の保証を両立
  • 条件の増加や分岐の変更に対して、堅牢かつ拡張しやすい設計
  • Pythonにおける動的クラス・高階関数の活用により、より柔らかな連鎖設計が可能

Pythonicとは、“分岐を構造に昇華させ、柔軟性と秩序を両立させる”ことであり、
Chain of Responsibilityパターンはその連鎖的設計力を、処理フローに注ぎ込むための技法である。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?