Decoupling is one of the prominent mantras in software engineering. Chain of responsibility helps to decouple sender of a request and receiver of the request with some trade-offs. Chain of responsibility is a design pattern where a sender sends a request to a chain of objects, where the objects in the chain decide themselves who to honor the request. If an object in the chain decides not to serve the request, it forwards the request to the next object in the chain.
Responsibility is outsourced. In a chain of objects, the responsibility of deciding who to serve the request is left to the objects participating in the chains. It is similar to ‘passing the question in a quiz scenario’. When the quiz master asks a question to a person, if he doesn’t knows the answer, he passes the question to next person and so on. When one person answers the question, the passing flow stops. Sometimes, the passing might reach the last person and still nobody gives the answer.
Welcome to behavioral design patterns. This is the first tutorial in behavioral category of our famous design pattern series.
Highlights of Chain of Responsibility
- Sender will not know which object in the chain will serve its request.
- Every node in chain will have the responsibility to decide, if they can serve the request.
- If node decides to forward the request, it should be capable of choosing the next node and forward it.
- There is a possibility where none of the node may serve the request.
Problems in Chain of Responsibility
There may be scenarios where a node is capable of solving the request but may not get a chance for it. Though there is a candidate who can solve the problem, but since nobody forwarded the request to it, it was not given a chance to serve and final result is the request goes unattended failure. This happens because of improper chain sequence. A chain sequence may not be suitable for all scenarios.
In object oriented design generally, every object is responsible for all its behaviour. Behaviour of an object is not transferred to other objects and is enclosed within itself. In chain of responsibility, some percentage of behaviour is offloaded to third party objects.
Chain of Responsibility Example
When thinking about nice examples for chain of responsibility pattern following list came to my mind. Coin sorting machine, ATM money dispenser, Servlet Filter and finally java’s own Exception Handling mechanism. We know exception handling better than anybody else and we are daily living with it. This qualifies as the best example for chain of responsibility.
We may have sequence of exceptions listed in catch statements and when there is an exception thrown, the catch list is scanned one by one from top. If first exception in catch can handle it the job is done, else the responsibility is moved to next in line and so on till it reaches finally block if we have one.
UML Diagram for Chain of Responsibility
Example Java Code
Following example code gives a sample implementation of chain of responsibility.
Chain.java
This is the interface that acts as a chain link.
public interface Chain {
void setNext(Chain nextInChain);
void process(Number request);
}
Number.java
This class is the request object.
public class Number {
private int number;
public Number(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
NegativeProcessor.java
This class is a link in chain series.
public class NegativeProcessor implements Chain {
private Chain nextInChain;
public void setNext(Chain c) {
nextInChain = c;
}
public void process(Number request) {
if (request.getNumber() < 0) {
System.out.println("NegativeProcess: " + request.getNumber());
} else {
nextInChain.process(request);
}
}
}
ZeroProcessor.java
This class is another link in chain series.
public class ZeroProcessor implements Chain {
private Chain nextInChain;
public void setNext(Chain c) {
nextInChain = c;
}
public void process(Number request) {
if (request.getNumber() == 0) {
System.out.println("ZeroProcessor: " + request.getNumber());
} else {
nextInChain.process(request);
}
}
}
PositiveProcessor.java
This class is another link in chain series.
public class PositiveProcessor implements Chain {
private Chain nextInChain;
public void setNext(Chain c) {
nextInChain = c;
}
public void process(Number request) {
if (request.getNumber() > 0) {
System.out.println("PositiveProcess: " + request.getNumber());
} else {
nextInChain.process(request);
}
}
}
TestChain.java
This class configures the chain of responsibility and executes it.
public class TestChain {
public static void main(String[] args) {
// Configure Chain of Responsibility
Chain c1 = new NegativeProcessor();
Chain c2 = new ZeroProcessor();
Chain c3 = new PositiveProcessor();
c1.setNext(c2);
c2.setNext(c3);
//Calling Chain of Responsibility
c1.process(new Number(99));
c1.process(new Number(-30));
c1.process(new Number(0));
c1.process(new Number(100));
}
}
Output for chain of responsibility example