The Chain of Responsibility pattern is implemented by defining a handler abstraction with a process method and a reference to the next handler, then linking concrete handler instances together so a request travels along the chain until one of them handles it.
Key Points: • Define a Handler interface or abstract class with a handle() method and a setNext()/next reference. • Each concrete handler decides whether it can process the request or should forward it to the next handler. • The client only needs a reference to the first handler in the chain, not the entire chain structure. • Handlers can be reordered, added, or removed by changing how they're linked, without touching handler logic. • A default fallback handler at the end of the chain can catch unhandled requests.
Example: A logging framework might chain a ConsoleLogger, FileLogger, and EmailLogger, where each handler decides based on severity whether to log the message and whether to also pass it to the next logger in the chain.
Code Example:
abstract class Handler {
protected Handler next;
Handler setNext(Handler next) {
this.next = next;
return next;
}
abstract void handle(Request request);
}
class ManagerHandler extends Handler {
void handle(Request request) {
if (request.getAmount() <= 1000) {
System.out.println("Approved by manager");
} else if (next != null) {
next.handle(request);
}
}
}Interview Tip: A concise interview answer is:
"I define a Handler abstraction with a handle() method and a link to the next handler, implement each concrete handler to process or forward the request, then chain instances together at setup time. The client only needs the head of the chain, which keeps handler logic decoupled from routing logic."