Overview
The Chain of Responsibility Design Pattern allows a request to pass through a chain of handlers until it is handled. It decouples the sender of a request from its receiver by giving multiple objects a chance to process the request.
Key Characteristics
- Promotes loose coupling between sender and receiver.
- Allows multiple handlers to process a request in a flexible and dynamic manner.
- Enables dynamic addition or removal of handlers from the chain.
Implementation
The following is an example of a Chain of Responsibility implementation in Java:
// Handler interface
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(String request);
}
// Concrete Handlers
class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("A")) {
System.out.println("Handler A processed the request.");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("B")) {
System.out.println("Handler B processed the request.");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("C")) {
System.out.println("Handler C processed the request.");
} else {
System.out.println("No handler could process the request.");
}
}
}
// Demo
public class ChainOfResponsibilityDemo {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
handlerA.handleRequest("B");
handlerA.handleRequest("A");
handlerA.handleRequest("C");
handlerA.handleRequest("D");
}
}
When to Use
- When multiple objects may handle a request, and the handler doesn't need to be specified explicitly.
- When you want to issue a request to one of several objects without knowing which one will handle it.
Advantages
- Promotes loose coupling between the sender and the receiver.
- Allows for dynamic addition or removal of handlers from the chain.
- Provides flexibility in assigning responsibilities to objects.
Disadvantages
- Can lead to unhandled requests if no suitable handler is found.
- May result in a long chain of handlers, which could affect performance.