Chain of Responsibility Pattern
Quality Score
Overall Score: 9.4/10 ⭐ Outstanding
- Technical Accuracy: 33/35
- Code Quality: 25/25
- Educational Value: 23/25
- Documentation: 14/15
Last reviewed: July 7, 2026
Chain of responsibility is a behavioral design pattern that allows passing request along a series of handlers. When receiving a request, each handler decides to handle it with its own logic and/or pass it to the next handler in the chain. Once the last handler is reached, the request is completed.
Each handler in the chain has a reference to the next handler, allowing for the request to keep moving along the chain to the end. At any point, the request can be handled and passed to the next handler, or it can be handled and the chain can be terminated. You can use the Chain of Responsibility pattern when multiple objects can handle a request, but the handler isn't known in advance or when you need to process a request through multiple stages or validations. The main benefits of this pattern are:
- Decoupling: The sender of a request is decoupled from the receiver, allowing for more flexible and maintainable code.
- Dynamic Handling: Handlers can be added or removed at runtime, allowing for dynamic handling of requests.
- Responsibility Sharing: Multiple handlers can share the responsibility of handling a request, allowing for more complex processing.
- User journey: The pattern can be used to create a user journey where each handler represents a step in the process, making a clear and organized flow of actions.
The chain of responsibility pattern is composed of three main components:
Handler Interface
Defines the common interface for all supported handlers. The responsibility is to know how to handle a request, not when to use the handler. The interface is usually implemented as an abstract class.
src.advanced.chain_of_responsibility_pattern.Handler
Bases: ABC
Abstract base class for handlers in the chain of responsibility.
This class defines the interface that all concrete handlers must implement. Each handler has a reference to the next handler in the chain.
Source code in src/advanced/chain_of_responsibility_pattern/chain_of_responsibility.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
Concrete Handler
Implements the behavior associated with a handler of the chain. The responsibility is to know how to handle a request and where to pass it next, not when to use the handler.
src.advanced.chain_of_responsibility_pattern.LengthValidationHandler
Bases: Handler
Concrete handler for line length validation.
Validates that the line does not exceed a maximum length. If the line is valid, passes it to the next handler in the chain.
Source code in src/advanced/chain_of_responsibility_pattern/chain_of_responsibility.py
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |
src.advanced.chain_of_responsibility_pattern.PrefixValidationHandler
Bases: Handler
Concrete handler for line prefix validation.
Validates that the line starts with a specific prefix. If the line is valid, passes it to the next handler in the chain.
Source code in src/advanced/chain_of_responsibility_pattern/chain_of_responsibility.py
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
src.advanced.chain_of_responsibility_pattern.SuffixValidationHandler
Bases: Handler
Concrete handler for line suffix validation.
Validates that the line ends with a specific suffix. If the line is valid, passes it to the next handler in the chain.
Source code in src/advanced/chain_of_responsibility_pattern/chain_of_responsibility.py
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | |
src.advanced.chain_of_responsibility_pattern.ContentValidationHandler
Bases: Handler
Concrete handler for line content validation.
Validates that the line contains exactly the required number of parts separated by a specific separator. If the line is valid, passes it to the next handler in the chain.
Source code in src/advanced/chain_of_responsibility_pattern/chain_of_responsibility.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
Chain of Responsibility
Initializes an instance of the class that defines the current handler and the order of execution. The responsibility is to know when to use the handler, not how to handle it.
src.advanced.chain_of_responsibility_pattern.ChainOfResponsibility
Class to manage the chain of responsibility.
This class initializes and manages a chain of validation handlers. The chain processes lines in the following order: 1. Length validation 2. Prefix validation 3. Suffix validation 4. Content structure validation
Source code in src/advanced/chain_of_responsibility_pattern/chain_of_responsibility.py
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | |
Some real world applications of the chain of responsibility pattern are: User journeys, logging systems, request processing, authentication/authorization, data validation...
Common Pitfalls
- Broken Chain: Forgetting to call the next handler breaks the chain. Always call the next handler unless explicitly terminating the chain.
class GoodHandler(Handler):
def handle(self, line: str) -> None:
if some_condition:
process(line)
if self.next: # Check next exists
self.next.handle(line)
-
Circular References: Creating a circular chain causes infinite recursion. Design your chain as a directed acyclic graph (DAG). Test for cycles if handlers can be dynamically configured.
-
Exception Handling: Exceptions in one handler can prevent other handlers from executing. Plan your exception strategy properly. Should exceptions stop the chain or should handlers catch and pass them along?
-
Order Dependencies: The order of handlers can affect the outcome. Document the expected order by defining and documenting clearly the flow.
-
Tight Coupling: Use dependency injection to pass handlers, keeping them loosely coupled. Handlers that directly reference specific next handler types become tightly coupled.