I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Design Patterns Uncovered: The Chain Of Responsibility Pattern

03.30.2010
| 52741 views |
  • submit to reddit

Today's pattern is the Chain of Responsibility, a simple way to decouple the handling of requests.

Chain of Responsibility in the Real World 

The idea of the Chain Of Responsibility is that it avoids coupling the sender of the request to the receiver, giving more than one object the opportunity to handle the request.  This process of delegation appears quite frequently in the real world where there is one interface for the customer to go through. One example could be a bank, where an application that you send in to the bank branch may be handled by one particular department. Another example is a vending machine, where you can put in any coin, but the coin is passed on to the appropriate receptacle to determine the amount that the coin is worth.  

Design Patterns Refcard
For a great overview of the most popular design patterns, DZone's Design Patterns Refcard is the best place to start. 

The Chain of Responsibility Pattern

The Chain of Responsibility is known as a behavioural pattern, as it's used to manage algorithms, relationships and responsibilities between objects. The definition of Chain of Responsibility provided in the original Gang of Four book on Design Patterns states: 

Gives more than one object an opportunity to handle a request by linking receiving objects together. 

Chain of Responsibility allows a number of classes to attempt to handle a request, independently of any other object along the chain. Once the request is handled, it completes it's journey through the chain.

Let's take a look at the diagram definition before we go into more detail.

 The Handler defines the interface required to handle request, while the ConcreteHandlers handle requests that they are responsible for.  If the ConcreteHandler cannot handle the request, it passes the request onto it's successor, which it maintains a link to. 

The objects in the chain just need to know how to forward the request to other objects.  This decoupling is a huge advantage, as you can change the chain at runtime. 

Would I Use This Pattern?

This pattern is recommended when either of the following scenarios occur in your application:

  • Multiple objects can handle a request and the handler doesn't have to be a specific object
  • A set of objects should be able to handle a request with the handler determined at runtime
  • A request not being handled is an acceptable outcome.

The pattern is used in windows systems to handle events generated from the keyboard or mouse. Exception handling systems also implement this pattern, with the runtime checking if a handler is provided for the exception through the call stack. If no handler is defined, the exception will cause a crash in the program, as it is unhandled.

In JavaEE, the concept of Servlet filters implement the Chain of Responsibility pattern, and may also decorate the request to add extra information before the request is handled by a servlet.

 

So How Does It Work In Java?

Now let's take a look at how we might implement the Chain of Responsibility with a code example. Let's use an email client as an example. You might set up some rules to move a message into a particular folder depending on who it's from. First we'll need to create our EmailHandler interface.

//Handler
public interface EmailHandler
{
//reference to the next handler in the chain
public void setNext(EmailHandler handler);

//handle request
public void handleRequest(Email email);
}

 

Now let's set up two concrete handlers, one for business mail and one for email originating from Gmail. These handlers pass on the request if it doesn't interest them 

public class BusinessMailHandler implements EmailHandler
{
private EmailHandler next;

public void setNext(EmailHandler handler)
{
next = handler;
}

public void handleRequest(Email email)
{
if(!email.getFrom().endsWith("@businessaddress.com")
{
next.handleRequest(email);
}
else
{
//handle request (move to correct folder)
}

}

}
public class GMailHandler implements EmailHandler
{
private EmailHandler next;

public void setNext(EmailHandler handler)
{
next = handler;
}

public void handleRequest(Email email)
{
if(!email.getFrom().endsWith("@gmail.com")
{
next.handleRequest(email);
}
else
{
//handle request (move to correct folder)
}

}

}

Now let's set up a client that manages the handlers - this will actually be our EmailProcessor. 

public class EmailProcessor
{
//maintain a reference to the previous handler so we can add the next one
private EmailHandler prevHandler;

public void addHandler(EmailHandler handler)
{
if(prevHandler != null)
{
prevHandler.setNext(handler);
}
prevHandler = handler;
}



}

This class allows us to add in new handlers at any stage. Finally, the email client itself uses the EmailProcessor to look after all incoming messages 

 

//email client 

public class EmailClient
{
private EmailProcessor processor;

public EmailClient()
{
createProcessor();

}

private void createProcessor()
{
processor = new EmailProcessor();
processor.addHandler(new BusinessMailHandler());
processor.addHandler(new PersonalMailHandler());
}


public void addRule(EmailHandler handler)
{
processor.addHandler(handler);
}

public void emailReceived(Email email)
{
processor.handleRequest(email);
}


public static void main(String[] args)
{

EmailClient client = new EmailClient();

}

}

If new rules, for forwarding email to particular folders are added, we can add the handler to our email processor at runtime using the addRule() method in the client.

Watch Out for the Downsides

As with the Observer pattern, Chain of Responsibility can make it difficult to follow through the logic of a particular path in the code at runtime. It's also important to note that there is the potential that the request could reach the end of the chain and not be handled at all.

Other Articles in This Series
The Observer Pattern
The Adapter Pattern
The Facade Pattern
The Factory Method Pattern
The Abstract Factory Pattern
The Singleton Pattern
The Strategy Pattern
The Visitor Pattern

The Decorator Pattern
The Proxy Pattern
The Command Pattern
The Chain of Responsibility Pattern
The Template Method Pattern

Next Up

We're going to look at the Command pattern later this week.

Tags:

Comments

Baptiste Wicht replied on Tue, 2010/03/30 - 7:36am

Very interesting. A clean Chain of Responsibility implementation. That's rare. We often see incorrect implementation of this powerful design pattern.

Mark Fisher replied on Tue, 2010/03/30 - 9:34am

Nice post. I just wanted to throw out another implementation option. When creating something like this, I typically consider an abstract base class, especially since the semantics of CoR require that the next handler be invoked if the current handler does not accept the request. There's a tradeoff, but if you will have a lot of contributing implementations, it's risky to expect that each one handle that CoR logic correctly. So, a base class might look like this:

public abstract class AbstractEmailHandler implements EmailHandler {

private volatile EmailHandler next;

public final void setNext(EmailHandler handler) {
this.next = handler;
}

public final void handleRequest(Email email) {
if (this.accept(email)) {
this.doHandle(email);
}
else {
this.next.handleRequest(email);
}
}

protected abstract boolean accept(Email email);

protected abstract void doHandle(Email email);

}

Then, the implementations can be a bit simpler. For example:

public GMailHandler extends AbstractEmailHandler {

protected boolean accept(Email email) {
return email.getFrom().endsWith("@gmail.com");
}

protected void doHandle(Email email) {
// move to correct folder
}
}

Of course, nothing prevents someone from implementing the interface directly, but the abstract class does offer a simpler option for extension (with tradeoffs, as is always the case when using the single chance for inheritance).

Cheers,

Mark

James Sugrue replied on Tue, 2010/03/30 - 11:06am in response to: Mark Fisher

Thanks for the example Mark.
The reason I didn't do the abstract base class was because of single inheritance, but it does make a bit more sense to do it this way.

 James

 

The Nonhacker replied on Tue, 2010/03/30 - 6:01pm

But we can do the example above looping though a List<EmailHandler>, and EmailHandler#handleRequest returns a boolean to signal a recommendation to use the next EmailHandler in the List.

- No need to embed the "EmailHandler next" boilerplate field

- You saved yourself effort from having to invoke "setNext(EmailHandler handler)"

- You saved the developers from the discrete effort of manually invoking "handleRequest"

 

 

Jari Mustonen replied on Thu, 2010/04/08 - 2:46pm

This method here:
public final void setNext(EmailHandler handler) {
this.next = handler;
}
should probably be
public final void setNext(EmailHandler handler) {
if ( this.next == null ) {
this.next = handler;
} else {
this.next.setNext(handler);
}
}

Ivo Limmen replied on Wed, 2010/06/09 - 1:34am

I always skip this pattern. I never pass of the responsibility using the interface but handle it within a proxy class. I would use the interface like this:

//Handler
public interface EmailHandler
{
//handle request
public void handleRequest(Email email);
}

And build a EmailHandler that can pass invoke to (or more) other EmailHandlers.

public CheckForSpamFirstEmailHandler implements EmailHandler 
{
private EmailHandler eh1;
private EmailHandler eh2;
public CheckForSpamFirstEmailHandler(EmailHandler eh1, EmailHandler2)
{
this.eh1 = eh1;
this.eh2 = eh2;
}
public void handleRequest(Email email)
{
this.eh1.handleRequest(email);
this.eh2.handleRequest(email);
}
}

This way you can use different strategies.

 

Diego Gusava replied on Sat, 2012/03/03 - 7:12pm

The class EmailProcessor should probably be

 

public class EmailProcessor {
	
	private EmailHandler successor;
	private EmailHandler first;
	
	public EmailProcessor(){
	}
	
	public void addEmailHandler(EmailHandler emailHandler){
		if(this.first == null){
			this.first = emailHandler;
		}else{
			this.successor.setNext(emailHandler);	
		}
		this.successor = emailHandler;
	}
	
	public void handleRequest(Email email){
		first.handleRequest(email);
	}
	
}

 

 

 

Arun Abraham replied on Mon, 2014/01/06 - 6:21am in response to: Diego Gusava

Diego, Why do you need a reference to both the successor and the parent/first, when one is sufficient to do the work ?

view sourceprint

Vijay Polsani replied on Thu, 2014/07/24 - 12:55am

The code for Processor should be for having a LinkedList iteration. Or use a regular Java List to store the sequence.

	public class EmailProcessor
	{
		//maintain a reference to the previous handler so we can add the next one
		private EmailHandler prevHandler;
		public void addHandler(EmailHandler handler)
		{
			handler.setNext(prevHandler);
			prevHandler = handler;
		} 

Complete Code:

public final class ComplainceHandlerProcessor {
	private ComplianceBatchHandler nextHandler;

	public ComplainceHandlerProcessor() {
		createProcessorChain();
	}

	private void createProcessorChain() {
		//FILO
		this.addHandler(new HeaderPopulateHandler());
		this.addHandler(new OffsetLookupHandler());
		this.addHandler(new ClientTrackingHandler());
	}

	public void addHandler(ComplianceBatchHandler handler) {
		handler.setNext(nextHandler);
		nextHandler = handler;
	}
	
	public void printHandlerChain() {
		System.out.print("List: " + nextHandler.toString());
	}

	public ComplianceBatchHandler callHandlerChain() {
		ComplianceBatchHandler temp = nextHandler;
		if (nextHandler != null)
			nextHandler = nextHandler.getNext();
		System.out.print("\nReturned Object: " + temp);
		return temp;
	}
}
The output would be: 
List: ClientTrackingHandler [next=OffsetLookupHandler [next=HeaderPopulateHandler [next=null]]]

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.