JAVA DESIGN PATTERNS

Behavioral Patterns - Chain of Responsibility Pattern

The chain of responsibility pattern is based on the same principle as written above. It decouples the sender of the request to the receiver. The only link between sender and the receiver is the request which is sent. Based on the request data sent, the receiver is picked. This is called “data-driven”. In most of the behavioral patterns, the data-driven concepts are used to have a loose coupling.

The responsibility of handling the request data is given to any of the members of the “chain”. If the first link of the chain cannot handle the responsibility, it passes the request data to the next level in the chain, i.e. to the next link. For readers, familiar with concepts of Java, this is similar to what happens in an Exception Hierarchy. Suppose the code written throws an ArrayIndexOutOfBoundsException. Now, this exception is because of some bug in coding and so, it gets caught at the correct level. Suppose, we have an application specific exception in the catch block. This will not be caught by that. It will find for an Exception class and will be caught by that as both the application specific exceptions and the ArrayIndexOutOfBoundsException are sub-classes of the class Exception.

Once get caught by the exception, which is the base class, it will then not look for any other exception. This is precisely the reason why, we get an “Exception is unreachable” message when we try to add a catch block with the exception below the parent exception catch block.

So, in short, the request rises in hierarchy till some object takes responsibility to handle this request.

It’s the same mechanism used for multi-level filtration. Suppose, we have a multi level filter and gravel of different sizes and shapes. We need to filter this gravel of different sizes to approx size categories. We will put the gravel on the multi-level filtration unit, with the filter of maximum size at the top and then the sizes descending. The gravel with the maximum sizes will stay on the first one and rest will pass, again this cycle will repeat until, the finest of the gravel is filtered and is collected in the sill below the filters. Each of the filters will have the sizes of gravel which cannot pass through it. And hence, we will have approx similar sizes of gravels grouped.

Let’s apply the same example in the form of code.

First, let’s talk about the request data. In this case, it is the gravel. We call it Matter. It has size and quantity. Now, the size determines whether it matches the size of filter or not and the quantity tells how much matter is below the size.

Matter.java

package bahavioral.chainofresponsibility;

public class Matter {
  // size of matter
private int size;
// quantity
private int quantity;

/**
* returns the size
*/
public int getSize() {
return size;
}

/**
* sets the size
*/
public void setSize(int size) {
this.size = size;
}

/**
* returns the quantity
*/
public int getQuantity() {
return quantity;
}

/**
* sets the quantity
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}

}// End of class

The next thing is now the base class. This base class in our case is Sill. Nothing escapes the Sill. All the matter is collected in the sill. Everything which cannot be filtered gets collected in the Sill. Like all the requests which cannot be handled at a lower level rise to higher level and are handled at the highest level.

Sill.java

package bahavioral.chainofresponsibility;

/**
* Sill.java
*
* This is the base class, you can say, which collects everything
* and nothing passes this. Whatever matter is remaining, and is
* still not filtered, is collected here.
*/
public class Sill {

  /**
* Method collect.
* Everything is collected here.
*/
public void collect(Matter gravel) {

}
}// End of class

And of course, the next class will be the chain. In the example, I have just created one single class called Filter1. This class extends from the Sill. And the chain grows on. Every class like Filter2, Filter3 etc extends from Filter1, Filter2 and so on.

Filter1.java
package bahavioral.chainofresponsibility;

/**
* This is a filter. This filters out the gravel and
* passes the rest to the next level.
*/
public class Filter1 extends Sill {

  private int size;

public Filter1(int size) {
this.size = size;
}

/**
* over-ridden method from base class
*/
public void collect(Matter gravel) {
    // for the entire quantity of matter
for(int i = 0; i < gravel.getQuantity(); i++) {
      // if gravel size is less than size of filter,
// the gravel will pass to the next level.
        if(gravel.getSize() < size) {
super.collect(gravel);
} else {
//collect here. that means, only matter with less
// size will pass...
}
    }    
  }
   
}// End of class

This is how, this pattern works. Based on principles of decoupling, the pattern is totally data-driven. The famous example is the Exception hierarchy.

The other advantage is distribution of responsibilities. There can be such a scenario when none of the objects in the chain can handle the request. In this case, the chain will discard the request. The basic object can also be an interface depending on needs.

Patterns
Creational Patterns
Factory Pattern
Abstract Factory Pattern
Singleton Pattern
Builder Pattern
Prototype Pattern
Structural Patterns
Adapter Pattern
Bridge Pattern
Composite Pattern
Decorator Pattern
Facade Pattern
Flyweight Pattern
Proxy Pattern
Behavioral Patterns
Chain of Responsibility Pattern
Command Pattern
Interpreter Pattern
Iterator Pattern
Mediator Pattern
Momento Pattern
Observer Pattern

State Pattern
Strategy Pattern
Template Pattern

Visitor Pattern
Use of this website constitutes acceptance of the AllAppLabs.com Terms and Conditions