Chain of Responsibility Pattern belongs to the Behavioral category of design patterns.
Why? Because it’s all about decoupling who sends a request from who handles it, and allowing multiple handlers the chance to act - one at a time.
It lets you,
- Pass a request along a chain of potential handlers
- Let each handler decide if it can process the request
- Stop the chain when one handler takes responsibility
- Easily extend or modify the chain without changing existing code
It’s like creating a support system where the request keeps getting passed along until someone says, “I got this! Let me take care of it.”
Taking an example of Customer Support Ticket System
Imagine you are reaching out to customer support for some issue regarding a recent purchase. Usually, this is what a typical support hierarchy looks like.
First, a bot tries to resolve your issue.
If that doesn't work, the ticket goes to a junior agent (L1 support).
Still unresolved? It escalates to a senior agent (L2) or a supervisor (L3).
Each level tries to handle the request, and passes it on, only if it can't resolve it at their level.
That is the Chain of Responsibility in action where each level gets a chance to help, passing it on only if needed.
What is the Chain of Responsibility Pattern?
It lets you build a chain of objects (handlers), where each one can either,
a) Handle the request, and/or
b) Pass it to the next handler in the chain
The sender doesn’t care who ends up handling the request. It just starts the chain.
The Middleware Pipeline
If you have ever worked with ASP.NET Core, Express.js, or similar web frameworks, you would already be familiar with this pattern.
When a request hits your server, it goes through a chain of middleware components which would look something like,
One middleware checks for authentication
Another one logs the request
Another checks if the user is authorized
Yet another serves the final response
Each one does its job (if needed) and then passes the request forward.
That is exactly how the Chain of Responsibility works.
Let’s See It in Code
Let’s imagine you are designing a web request pipeline. You want to handle things like authentication, logging, and actual request processing. But you don’t want all of that cluttered in one place. Instead, you break it down into separate steps, and each step (middleware) focuses on just one responsibility.
You build each middleware like a link in a chain, and then just pass the request along the chain until someone handles it (or the final handler sends a response). It’s a clean, flexible, and intuitive setup.
Here is how it looks in simple pseudocode,
// Step 1: Define a base Handler
Class Middleware
Property nextMiddleware
Method SetNext(middleware)
this.nextMiddleware = middleware
return middleware
Method Handle(request)
CallNext(request)
Method CallNext(request)
If nextMiddleware exists:
nextMiddleware.Handle(request)
// Step 2: Concrete Middlewares
Class AuthMiddleware extends Middleware
Method Handle(request)
If request has valid token:
Print("Authenticated")
CallNext(request)
Else:
Print("Unauthorized request")
Stop
Class LoggingMiddleware extends Middleware
Method Handle(request)
Print("Logging request: " + request.url)
CallNext(request)
Class FinalHandler extends Middleware
Method Handle(request)
Print("Processing request and sending response.")
//caller logic
//Create Handlers
auth = new AuthMiddleware()
logger = new LoggingMiddleware()
handler = new FinalHandler()
//Setup the Chain
auth.SetNext(logger)
logger.SetNext(handler)
//Prepare Incoming Request
request = {
url: "/api/data",
token: "a valid token"
}
//Start the Chain
auth.Handle(request)
What Did We Achieve?
- Handlers are loosely coupled
- Order of processing is flexible
- Easy to plug in new middlewares
- Request is processed step by step, each part is doing its dedicated job
When Should You Use It?
- When multiple objects can handle a request, and you don’t want the sender to care who handles it
- When you want to process requests step by step
- When you want to enable flexible and pluggable flows
Use Cases?
- Middleware in web frameworks (Express, ASP.NET Core)
- Event handling systems (GUI toolkits, games)
- Logging pipelines
- Tech support systems (Level 1 → Level 2 → Level 3)
- Access control chains
To summarize it would be apt to say,
Chain of Responsibility Pattern is like a relay baton passed along a chain of handlers. Each gets a chance to process, modify, or reject the request.
Hope this example gave you a clear picture of how the Chain of Responsibility Pattern works, especially in middleware like scenarios, where each handler does one job and passes the request forward. This keeps your code clean, modular, and easy to extend.
Next up in the series: Mediator Pattern. Let’s meet there!
Top comments (0)