Chain of Responsibility Pattern
Chain of Responsibility: start from the problem
See the responsibilities
A request must pass validation and permission checks before a handler acts. Hard-coding all checks into one operation makes it difficult to understand which step stops a request.
This is a behavioral pattern lesson. Follow the responsibilities, inspect the small JavaScript example and compare the design choices. The example is local teaching code; its boundary is explained before you apply the idea to a real service.
What you’ll learn
- Explain the problem Chain of Responsibility addresses and the roles involved.
- Follow the example and distinguish this pattern from nearby alternatives.
- Choose when the benefit justifies the extra responsibilities and testing.
How the responsibilities work
Chain of Responsibility passes a request through ordered handlers. Each can handle it, reject it or forward it under a shared rule. Some chains stop at the first matching handler; middleware pipelines often run several handlers before a final action. State which variant you use.
Our pipeline checks name and permission before returning success. A rejected request stops the chain. The example does not implement production authentication; it illustrates ordered responsibility.
Follow a small example
Read the JavaScript from top to bottom and compare the expected output. The values are chosen to make this pattern’s responsibility visible. This example runs in one local execution context; it does not create remote services, durable storage or production access controls.
JavaScript · local teaching example
const handlers = [
request => request.name ? null : 'missing name',
request => request.allowed ? null : 'forbidden'
];
function handle(request) {
for (const check of handlers) { const error = check(request); if (error) return error; }
return 'accepted';
}
console.log(handle({name: 'order', allowed: false}));
console.log(handle({name: 'order', allowed: true}));Expected output
forbidden
acceptedChoose a design and inspect the consequence
Compare the design choices
Compare the visible consequences. With JavaScript enabled, choose an option in each scenario to assemble your decision record.
This is an exploratory design exercise. It does not run infrastructure, measure capacity or replace the lesson’s quiz.
Apply the pattern to two situations. Select one option in each situation to build a decision record. Every option and its consequence stays visible, and you can change your choices.
When it helps—and what it costs
Use it for a clear ordered set of independent checks or routing handlers. Record which handlers may terminate, transform or invoke the next stage.
Ordering can change security and behaviour. Missing forwarding can silently drop work; forwarding twice can duplicate effects. Long chains make ownership difficult, so use clear stop rules and instrumentation.
Distinguish the neighbouring patterns
Decorator wraps an object contract and can surround a delegated operation. Chain handlers decide where a request proceeds. Mediator coordinates relationships among participants rather than only a linear pipeline.
Follow wrapping behaviour around delegation, coordination among participants, gateway checks and routing to compare the specific responsibility before combining patterns.
Check your pattern reasoning
Check your pattern reasoning
Name the responsibility before choosing the pattern
For Chain of Responsibility, describe the problem, the participating roles and the observable contract. Use the example as a starting point and test the boundaries identified in the trade-offs. A pattern name alone does not establish correctness or performance.
Return to the design-pattern guide to compare families, or apply the idea alongside gateway checks and routing.
Reaching the recap and completing the quizzes are separate milestones.