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

ClientHandler AHandler BHandler Crequestpasspass
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.