0
1

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文に依存せず、構造で制御できるようになるのが特徴。
リクエスト処理、バリデーション、ミドルウェア的な実装に適している。


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

❌ 複数の条件分岐による責務処理

if request.type == "auth":
    handle_auth(request)
elif request.type == "log":
    handle_log(request)
elif request.type == "notify":
    handle_notify(request)

→ 条件が増えるほどコードが分岐し、メンテナンスが困難に


✅ 各責務をチェーンでつなぎ、順に処理させる

auth.set_next(log).set_next(notify)
auth.handle(request)

処理フローをコードでなくオブジェクト構造で制御


2. 基本構造

✅ Handler基底クラス

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

    def set_next(self, handler):
        self._next = handler
        return handler

    def handle(self, request):
        if self._next:
            return self._next.handle(request)

✅ Concrete Handlers(処理の実体)

class AuthHandler(Handler):
    def handle(self, request):
        if request.get("auth"):
            print("AuthHandler: 認証済み")
        else:
            print("AuthHandler: 未認証。処理停止")
            return
        super().handle(request)

class LogHandler(Handler):
    def handle(self, request):
        print("LogHandler: ログ記録")
        super().handle(request)

class NotifyHandler(Handler):
    def handle(self, request):
        print("NotifyHandler: 通知送信")
        super().handle(request)

✅ 使用例

request = {"auth": True}

auth = AuthHandler()
log = LogHandler()
notify = NotifyHandler()

auth.set_next(log).set_next(notify)

auth.handle(request)

出力:

AuthHandler: 認証済み
LogHandler: ログ記録
NotifyHandler: 通知送信

3. Python的応用:関数ベースのチェーン構築

def auth_middleware(req, next_handler):
    if req.get("auth"):
        print("[auth] pass")
        return next_handler(req)
    print("[auth] reject")

def log_middleware(req, next_handler):
    print("[log] recorded")
    return next_handler(req)

def notify_middleware(req, next_handler):
    print("[notify] sent")
    return next_handler(req)

def build_chain(*middlewares):
    def call(req):
        def _call(index):
            if index >= len(middlewares):
                return
            return middlewares[index](req, lambda r: _call(index + 1))
        return _call(0)
    return call
chain = build_chain(auth_middleware, log_middleware, notify_middleware)
chain({"auth": True})

ミドルウェアスタイルの非同期・非ブロッキング処理に応用可能


4. 実務ユースケース

✅ Webフレームワークのミドルウェアチェーン

→ 認証、バリデーション、ログ、変換処理など段階的に通す


✅ バリデーションロジックの組み合わせ

→ 入力値に対する検証ロジックを順に適用してエラー検出


✅ エラーハンドリングの委譲処理

例外の発生場所によって異なる責任者に処理を委譲


✅ チェックポイント式のビジネスフロー構築

→ 顧客データ、与信、在庫、承認などを順に確認するプロセス設計


5. よくある誤用と対策

❌ チェーン内で次の処理を忘れて中断

→ ✅ 常に super().handle(request) を呼ぶ or 明示的に next() を設計に含める


❌ 全てのハンドラーが必ず呼ばれてしまう

→ ✅ 処理継続の条件分岐を設計内に明示的に持たせる


❌ チェーンが長くなりすぎて可視性低下

→ ✅ ハンドラ構成を外部で定義し、ログや可視化支援を取り入れる


結語

Chain of Responsibilityパターンとは、“責任を持った処理を順に流し、全体をしなやかに制御する構造”である。

  • if文を排除し、オブジェクト指向的に処理を分割・接続
  • 構造化された処理の流れにより、再利用・構成変更・テストが容易に
  • Pythonでは、クラスベース・関数ベースの両面から柔軟にチェーン設計が可能

Pythonicとは、“条件ではなく構造で制御する”。
Chain of Responsibilityパターンはその流れと責任を、静かに繋ぎ、整えるための技法である。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?