What It Is
The Chain of Responsibility pattern passes a request along a chain of handlers. Each handler either deals with the request or hands it to the next one. The sender only knows the first link — never who will actually solve it.
Example: A Support Line
A problem enters at the chat bot. What the bot cannot fix goes to tech support; what tech support cannot fix goes to the manager, who handles everything that arrives.
Pass it on until someone can
"No internet" travels one step and stops at tech support; the refund request travels the whole chain to the manager. The caller wrote the same one line both times.
Output: complete Python program
from dataclasses import dataclass
from typing import Callable
@dataclass
class Handler:
name: str
can_fix: Callable[[str], bool]
next_handler: "Handler | None" = None
def handle(self, problem: str) -> None:
if self.can_fix(problem):
print(self.name, "solved:", problem)
return
print(self.name, "passes it on")
if self.next_handler is not None:
self.next_handler.handle(problem)
manager = Handler("manager", lambda problem: True)
tech = Handler("tech support", lambda problem: problem == "no internet", manager)
bot = Handler("chat bot", lambda problem: problem == "forgot password", tech)
bot.handle("no internet")
print("---")
bot.handle("refund request")
When to Use It
Use it when several parties might handle a request and the right one is not known in advance — support escalation, middleware, event handling, approval workflows.
Skip it when the handler is always known — call it directly. A chain with one link, or one that always ends at the same link, is a plain function call in costume.
Pros and Cons
Pros: sender and receivers are decoupled; links can be added, removed and reordered freely; each handler stays small.
Cons: no guarantee anyone handles the request — a broken chain swallows it silently; following a request through many links makes debugging slower.