Behavioral Pattern
Chain of Responsibility
Pass requests along a chain of handlers. Each handler decides to process the request or pass it to the next handler in the chain.
10 min readMedium Priority
1What is Chain of Responsibility?
Real-World Analogy
Tech Support Escalation
L1 support handles basic issues. If they can't help, they escalate to L2. L2 escalates to L3. Each level tries to handle before passing up.
Approval Workflow
Expense request goes to manager. If over their limit, goes to director, then VP. Each approves if within their authority.
Chain of Responsibility decouples the sender of a request from its receivers. Multiple handlers are chained together, and each gets a chance to process the request or pass it along. The client doesn't know which handler will process the request.
Chain Flow
Request passes through chain until a handler processes it.
2Implementation
Chain of Responsibility - Expense Approval
// ========== Handler Interface ==========
abstract class ExpenseHandler {
protected ExpenseHandler next;
public ExpenseHandler setNext(ExpenseHandler handler) {
this.next = handler;
return handler; // For chaining
}
public void handle(ExpenseRequest request) {
if (canHandle(request)) {
process(request);
} else if (next != null) {
next.handle(request);
} else {
System.out.println("No handler for: $" + request.getAmount());
}
}
protected abstract boolean canHandle(ExpenseRequest request);
protected abstract void process(ExpenseRequest request);
}
// ========== Request ==========
class ExpenseRequest {
private String description;
private double amount;
public ExpenseRequest(String desc, double amount) {
this.description = desc;
this.amount = amount;
}
public double getAmount() { return amount; }
public String getDescription() { return description; }
}
// ========== Concrete Handlers ==========
class Manager extends ExpenseHandler {
private static final double LIMIT = 1000;
@Override
protected boolean canHandle(ExpenseRequest req) {
return req.getAmount() <= LIMIT;
}
@Override
protected void process(ExpenseRequest req) {
System.out.println("Manager approved: " + req.getDescription() +
" ($" + req.getAmount() + ")");
}
}
class Director extends ExpenseHandler {
private static final double LIMIT = 10000;
@Override
protected boolean canHandle(ExpenseRequest req) {
return req.getAmount() <= LIMIT;
}
@Override
protected void process(ExpenseRequest req) {
System.out.println("Director approved: " + req.getDescription() +
" ($" + req.getAmount() + ")");
}
}
class VP extends ExpenseHandler {
private static final double LIMIT = 100000;
@Override
protected boolean canHandle(ExpenseRequest req) {
return req.getAmount() <= LIMIT;
}
@Override
protected void process(ExpenseRequest req) {
System.out.println("VP approved: " + req.getDescription() +
" ($" + req.getAmount() + ")");
}
}
// ========== Usage ==========
public class Main {
public static void main(String[] args) {
// Build chain
ExpenseHandler manager = new Manager();
ExpenseHandler director = new Director();
ExpenseHandler vp = new VP();
manager.setNext(director).setNext(vp);
// Process requests
manager.handle(new ExpenseRequest("Office supplies", 500));
manager.handle(new ExpenseRequest("Conference", 5000));
manager.handle(new ExpenseRequest("Training program", 50000));
manager.handle(new ExpenseRequest("New building", 500000));
}
}Output:
Manager approved: Office supplies ($500) Director approved: Conference ($5000) VP approved: Training program ($50000) No handler for: $500000
3Real-World Applications
Servlet Filters
Authentication, logging, compression filters in chain.
Middleware
Express.js/Spring middleware chains for request processing.
Event Bubbling
DOM events bubble up from child to parent elements.
Exception Handling
Catch blocks form a chain for exception handling.
4Interview Follow-up Questions
Interview Follow-up Questions
Common follow-up questions interviewers ask
5Key Takeaways
1Chain of Responsibility passes requests through a chain of handlers.
2Each handler decides to process or pass along.
3Decouples sender from receivers - sender doesn't know who handles.
4Request may go unhandled if no handler matches.
5Different from Decorator: CoR stops when handled, Decorator always continues.
6Examples: middleware, approval workflows, event handling.