Intent
It is belongs to behavioral design patterns catalog.Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
Explanation
Real world example
The Orc King gives loud orders to his army. The closest one to react is the commander, then officer and then soldier. The commander, officer and soldier here form a chain of responsibility.In plain words
It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler.Wikipedia says
In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.Advantage of Chain of Responsibility Pattern
- It reduces the coupling.
- It adds flexibility while assigning the responsibilities to objects.
- It allows a set of classes to act as one; events produced in one class can be sent to other handler classes with the help of composition.
Structure
Participants
1. Handler
- defines an interface for handling requests.
- (optional) implements the successor link.
2. ConcreteHandler
- handles requests it is responsible for.
- can access its successor.
- if the ConcreteHandler can handle the request, it does so; otherwise
- it forwards the request to its successor.
3. Client
- initiates the request to a ConcreteHandler object on the chain.
Collaborations
- When a client issues a request, the request propagates along the chain until a ConcreteHandler object takes responsibility for handling it.
Source code
Step 1 : First we have the request class
public class Request {
private final RequestType requestType;
private final String requestDescription;
private boolean handled;
public Request(final RequestType requestType, final String requestDescription) {
this.requestType = Objects.requireNonNull(requestType);
this.requestDescription = Objects.requireNonNull(requestDescription);
}
public String getRequestDescription() { return requestDescription; }
public RequestType getRequestType() { return requestType; }
public void markHandled() { this.handled = true; }
public boolean isHandled() { return this.handled; }
@Override
public String toString() { return getRequestDescription(); }
}
public enum RequestType {
DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX
}
Step 2 : Then the request handler hierarchy
public abstract class RequestHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class);
private RequestHandler next;
public RequestHandler(RequestHandler next) {
this.next = next;
}
public void handleRequest(Request req) {
if (next != null) {
next.handleRequest(req);
}
}
protected void printHandling(Request req) {
LOGGER.info("{} handling request \"{}\"", this, req);
}
@Override
public abstract String toString();
}
public class OrcCommander extends RequestHandler {
public OrcCommander(RequestHandler handler) {
super(handler);
}
@Override
public void handleRequest(Request req) {
if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) {
printHandling(req);
req.markHandled();
} else {
super.handleRequest(req);
}
}
@Override
public String toString() {
return "Orc commander";
}
}
// OrcOfficer and OrcSoldier are defined similarly as OrcCommander
Step 3 :Then we have the Orc King who gives the orders and forms the chain
public class OrcKing {
RequestHandler chain;
public OrcKing() {
buildChain();
}
private void buildChain() {
chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null)));
}
public void makeRequest(Request req) {
chain.handleRequest(req);
}
}
Step 4 : Then it is used as follows
OrcKing king = new OrcKing();
king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle"
king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner"
king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax"
Applicability
Use Chain of Responsibility when- more than one object may handle a request, and the handler isn't known a prior. The handler should be ascertained automatically
- you want to issue a request to one of several objects without specifying the receiver explicitly
- the set of objects that can handle a request should be specified dynamically.