Chain of Responsibility Pattern Design in Java

The chain of responsibility pattern comes first under behavioral patterns in object-oriented programming. The design pattern consists of processing objects and command objects. The processing objects feature the logic that defines what type of command objects, it can process. The ones that are not defined in that processing object, are passed to the others in the chain.

The Chain of Responsibility Pattern

According to the Gang of Four:

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.

In the standard chain of responsibility model variant, some processing object may act as ‘dispatchers’, which means, they are able to send the command out in different directions. This forms a ‘tree of responsibility’. There are some cases, where this process runs recursively. The processing object would be calling higher-up processing objects with command in order to solve a smaller part of the problem. This recursion tends to continue until either the command is processed or the whole responsibility tree is explored.

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Pattern“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use author discount to purchase this book by using code- “AUTHDIS40“.
Spring-5-Design-Pattern

To design, versatile and reusable object-oriented software, there are 23 well-known design patterns, the chain of responsibility is one of them. The idea of the chain of responsibility is not to link the sender of the request and the receiver. This gives the opportunity to more than one object to carry out the command. Although, when the receiver is not capable of solving the problem, it sends the problem to another object of the tree. In real life, the vending machine is a suitable example which is easy to comprehend as well. When the buyer inserts the coin and presses the button for a particular item, the coin is passed from object to object until it reaches the one which was selected by the buyer.

Benefits of Chain of Responsibility Pattern

There are following benefits of this pattern.

  • It reduces the coupling between sender and receiver objects in the system to handle a request.
  • It is more flexible to assign the responsibility to another referenced object.
  • This pattern makes a chains of objects using composition, and this set of objects work as a single unit.

UML Class Diagram for this pattern

Let’s see the following UML diagram is showing the all components of chain of responsibility design pattern:

Chain of Responsibility Pattern

Handler

This is an abstract class or interface in the system to handle request.

ConcreteHandler

These are concrete classes, implement Handler to handle the request, or it passes same request to the next successor of the handler chain.

Client

It is main application class to initiate the request to the handlers objects on the chain.

The structure of the chain of responsibility is defined to have a Handler. The Handler is the object which defines the request or the problem. The other part is known as Concrete handlers, they are the receiver objects. The handler sends the problem to the first receiver object, if that object is unable to handle the request, it passes on that request to the successive receiver object that, it is linked to. The request is passed until it reaches to the receiving object which is able to solve that problem. The chain of responsibility reduces the complexities between objects’ interconnections. The sender (handler) of the request only need to have the reference to the receiver object which is at the head of the chain and each receiver object need to have the reference to the successive receiver object only.

Example for Chain of Responsibility Design Pattern Implementation

The chain of responsibility design pattern is designed for certain scenarios when they occur in an application. For example, when more than one object is capable of handling the request and it does not have to be a particular object and with the handler determined at run-time, multiple objects must be able to handle the request.

The design enables the sender to generate a request and pass it on the tree without having to know which object is capable of handling the request. The chain of responsibility can be designed in different languages. For example, Java, C#, crystal, and python.

This real-world code demonstrates the Chain of Responsibility pattern in which several linked managers and executives can respond to a purchase request or hand it off to a superior. Each position has can have its own set of rules which orders they can approve.

Step 1: Create an abstract Approver class.
Approver.java

/**
 * 
 */
package com.doj.patterns.behavior.chainofresp;

/**
 * @author Dinesh.Rajput
 *
 */
public abstract class Approver {
	
	protected Approver successor;

	public void setSuccessor(Approver successor){
		this.successor = successor;
    }

	public abstract void processRequest(Purchase purchase);
	
}

Step 2: Create concrete classes extending the approver class.
Director.java

/**
 * 
 */
package com.doj.patterns.behavior.chainofresp;

/**
 * @author Dinesh.Rajput
 *
 */
public class Director extends Approver {

	@Override
	public void processRequest(Purchase purchase) {
		if(purchase.get_amount() < 10000.0){
			System.out.println(this.getClass().getSimpleName()+" approved request #"+ purchase.get_number());
		}else if (successor != null){
			successor.processRequest(purchase);
		}
	}
}

VicePresident.java

/**
 * 
 */
package com.doj.patterns.behavior.chainofresp;

/**
 * @author Dinesh.Rajput
 *
 */
public class VicePresident extends Approver {

	@Override
	public void processRequest(Purchase purchase) {
		if(purchase.get_amount() < 25000.0){
			System.out.println(this.getClass().getSimpleName()+" approved request #"+ purchase.get_number());
		}else if (successor != null){
			successor.processRequest(purchase);
		}
	}

}

President.java

/**
 * 
 */
package com.doj.patterns.behavior.chainofresp;

/**
 * @author Dinesh.Rajput
 *
 */
public class President extends Approver {

	@Override
	public void processRequest(Purchase purchase) {
		if(purchase.get_amount() < 100000.0){
			System.out.println(this.getClass().getSimpleName()+" approved request #"+ purchase.get_number());
		}else {
			System.out.println("Request #"+purchase.get_number()+" requires an executive meeting!");
		}
	}

}

Step 3: Create a demo class.

Create different types of approvers. Assign them limit of amount of a purchase and if purchase limit beyond the approver right then he delegates to higher level approver. Next approver in each approver represents the part of the chain.

ChainPatternDemo.java

/**
 * 
 */
package com.doj.patterns.behavior.chainofresp;

/**
 * @author Dinesh.Rajput
 *
 */
public class ChainPatternDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
	
		// Setup Chain of Responsibility
		Approver dinesh = new Director();
		Approver arnav = new VicePresident();
		Approver anamika = new President();

		dinesh.setSuccessor(arnav);
		arnav.setSuccessor(anamika);

		// Generate and process purchase requests
		Purchase purchase = new Purchase(1000, 3050.00, "Library Books");
		dinesh.processRequest(purchase);

		purchase = new Purchase(1001, 30500.10, "Lab Machines");
		dinesh.processRequest(purchase);

		purchase = new Purchase(1002, 130500.00, "Apple Mac Books");
		dinesh.processRequest(purchase);
	}

}

Step 4: Let’s run this demo class and verify the output.

Director approved request #1000
President approved request #1001
Request #1002 requires an executive meeting!

Previous
Next