0
0

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(責任の連鎖)パターンは、
複数のオブジェクトに順に処理を委譲し、ある条件を満たすものが責任を引き受けて処理を完了するための設計パターンである。

この構造により、送信者(リクエスト元)と受信者(処理実体)の結合を疎に保ちながら、柔軟で拡張可能な処理フローを実現する。


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

❌ 条件分岐が集中した処理ロジック

if request.type == "auth":
    ...
elif request.type == "log":
    ...

→ 新しい責任の追加で、if-elseの嵐が発生し、拡張性が低下


✅ 各処理単位を責任としてチェーンで接続し、順に評価する

auth.set_next(logger).set_next(handler)
auth.handle(request)

各処理が責任を持って処理・パスを判断。拡張も容易


2. 基本構造

✅ Handler(共通インターフェース)

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)

✅ ConcreteHandler(実処理)

class AuthHandler(Handler):
    def handle(self, request):
        if request.get("auth"):
            print("認証成功")
        else:
            print("認証失敗 → 次へ")
            return super().handle(request)

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

class FinalHandler(Handler):
    def handle(self, request):
        print("最終処理を実行")

✅ 使用例

auth = AuthHandler()
log = LogHandler()
final = FinalHandler()

auth.set_next(log).set_next(final)

request = {"auth": True}
auth.handle(request)

出力:

認証成功
ログ記録中...
最終処理を実行

3. Python的応用:デコレータ的連鎖処理にも適用可能

class Middleware:
    def __init__(self, next=None):
        self.next = next

    def handle(self, request):
        if self.next:
            self.next.handle(request)

class RateLimiter(Middleware):
    def handle(self, request):
        if request.get("rate_limit_ok", True):
            print("レート制限クリア")
            super().handle(request)
        else:
            print("レート制限ブロック")

class Validator(Middleware):
    def handle(self, request):
        if "user" in request:
            print("入力バリデーション成功")
            super().handle(request)
        else:
            print("バリデーション失敗")
chain = RateLimiter(Validator(FinalHandler()))
chain.handle({"user": "alice", "rate_limit_ok": True})

4. 実務ユースケース

✅ Webアプリケーションのリクエスト処理パイプライン

→ 認証 → ログ → バリデーション → ビジネスロジック などを責任の連鎖で構築


✅ ロガー・監視・セキュリティなどの横断的処理

→ 事前処理・後処理を独立した責任単位として組み込む


✅ イベント処理・UIイベントチェーン

→ 特定のコンポーネントがイベントを処理しなければ、次のコンポーネントへ委譲


✅ フィルタチェーン設計(例:セキュリティチェック → XSS → トークン検証)

中間層で責任を逐次消化し、柔軟に拡張可能


5. よくある誤用と対策

❌ 全ての処理が責任を持ってしまう

→ ✅ 各ハンドラーは「処理する/しない」を明確に判断すべき


❌ チェーン構成がハードコードされている

→ ✅ 柔軟にハンドラーを組み替えられるように設計すべき


❌ 次のハンドラーへの委譲が必須になっている

→ ✅ 最終処理やエラーストップなど連鎖を止める設計も組み込むべき


結語

Chain of Responsibilityパターンとは、“責任の流れを構造として連鎖させ、柔軟に制御を渡す”ためのデザイン技法である。

  • 処理の流れをモジュール化・分離し、拡張性と順応性を両立
  • 各責任単位が、受ける/渡すの判断を担うことで柔軟な制御が実現
  • Pythonではオブジェクト指向構造に加え、動的なハンドラー構成・関数型設計との親和性も高い

Pythonicとは、“制御構造を流れのようにしなやかに構築する”ことであり、
Chain of Responsibilityパターンはその制御の意志を、連鎖する責任という形で表現する設計技法である。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?