CHAIN OF RESPONSIBILITY

Chain of responsibility pattern is used to achieve lose coupling in software design where a request from client is passed to a chain of objects to process them. Then the object in the chain will decide themselves who will be processing the request and whether the request is required to be sent to the next object in the chain or not.

When there is more than one objects that can handle or fulfill a client request, the pattern recommends giving each of these objects a chance to process the request in some sequential order. Applying the pattern in such a case, each of these potential handlers can be arranged in the form of a chain, with each object having a reference to the next object in the chain. The first object in the chain receives the request and decides either to handle the request or to pass it on to the next object in the chain. The request flows through all objects in the chain one after the other until the request is handled by one of the handlers in the chain or the request reaches the end of the chain without getting processed.

Let’s see the example of chain of responsibility pattern in JDK and then we will proceed to implement a real life example of this pattern. We know that we can have multiple catch blocks in a try-catch block code. Here every catch block is kind of a processor to process that particular exception. So when any exception occurs in the try block its send to the first catch block to process. If the catch block is not able to process it, it forwards the request to next object in chain i.e. next catch block. If even the last catch block is not able to process it, the exception is thrown outside of the chain to the calling program.

Other examples are 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.

Example:

In ATM Dispense machine, the user enters the amount to be dispensed and the machine dispense amount in terms of defined currency bills such as 50$, 20$, 10$ etc. If the user enters an amount that is not multiples of 10, it throws error.

package com.myjavablog.behavioural.COR;

//This class is a request object.
public class Number {

private int number;

public int getNumber(){
return number;
}

public Number(int number){
this.number = number;
}
}

package com.myjavablog.behavioural.COR;

//This interface acts as a chain link
public interface Chain {

public void setNext(Chain nextInChain);
public void process(Number request);
}

package com.myjavablog.behavioural.COR;

public class PositiveNumberProcessor implements Chain {

private Chain nextInChain;

@Override
public void setNext(Chain c) {
this.nextInChain = c;
}

@Override
public void process(Number request) {

if(request.getNumber() > 0){
System.out.println("PositiveNumberProcessor : "+ request.getNumber());
}else {
nextInChain.process(request);
}
}
}

package com.myjavablog.behavioural.COR;

public class NegativeNumberProcessor implements Chain {

private Chain nextInChain;

@Override
public void setNext(Chain c) {
this.nextInChain = c;
}

@Override
public void process(Number request) {

if(request.getNumber() < 0){
System.out.println("NegativeNumberProcessor : "+ request.getNumber());
}else {
nextInChain.process(request);
}
}
}

package com.myjavablog.behavioural.COR;

public class ZeroProcessor implements Chain {

private Chain nextInChain;

@Override
public void setNext(Chain c) {
this.nextInChain = c;
}

@Override
public void process(Number request) {

if(request.getNumber() == 0){
System.out.println("ZeroProcessor : "+ request.getNumber());
}else {
nextInChain.process(request);
}
}
}

package com.myjavablog.behavioural.COR;

public class CORPatternTest {

public static void main(String[] args) {

//Configure chain of responsibility
Chain c1 = new NegativeNumberProcessor();
Chain c2 = new ZeroProcessor();
Chain c3 = new PositiveNumberProcessor();
c1.setNext(c2);
c2.setNext(c3);

//Calling chain of responsibility
c1.process(new Number(99));
c1.process(new Number(-76));
c1.process(new Number(0));
c1.process(new Number(100));

}
}

Output:

PositiveNumberProcessor : 99
NegativeNumberProcessor : -76
ZeroProcessor : 0
PositiveNumberProcessor : 100

When to use the Chain of Responsibility Pattern:

Use Chain of Responsibility when

  • More than one object may handle a request, and the handler isn’t known a priority. 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.

Chain of Responsibility Pattern Examples in JDK:

  • java.util.logging.Logger#log ()
  • javax.servlet.Filter#doFilter ()

Leave a Comment

Bitnami