CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

Using the Chain of Responsibility Pattern

It’ll never be the most commonly used pattern in your design toolbox, but I’ve occasionally had good results using a “Chain of Responsibility” (CoR) pattern to organize wildly variable logic.  Most importantly, my team recently used the pattern a couple of times in some code that’s likely to be supported by another group.  It’s likely that I’ll need to explain the “Chain of Responsibility” pattern to another developer, so here’s my practice run.

 

The original Gang of Four definition of CoR is:

 

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. There is a potentially variable number of "handler" objects and a stream of requests that must be handled. Need to efficiently process the requests without hard-wiring handler relationships and precedence, or request-to-handler mappings.

 

One of the most common pattern usages is to use a series of Strategy classes to handle different types of requests, with some sort of Factory pattern to obtain the proper handler.  In other cases the logic to select the proper Strategy class becomes much more complex than simply running one property of the request through a case statement.  That’s when you might reach for the Chain of Responsibility pattern.  In the CoR pattern each handler contains the logic to test for its applicability to a request.  If it can’t handle the request it’ll send the request to the next handler in the chain.  The original client is completely unaware of the handler chaining.

 

Here’s a real world scenario taken from a shipping system I prototyped several years ago (but didn’t get to build).  Let’s say your company takes orders electronically from either the web or some sort of web service.  The steps to complete and handle an order vary widely based on the customer, size of order, destination, and a host of other things.  The business logic changes rapidly as special cases crop up and disappear.  Let’s say that we have these contrived, fictional cases:

 

  1. Orders to the European Community require a different set of value added tax calculations and we do international shipping through a different set of carriers
  2. Large bulk orders are handled separately within the warehouse and might go to different shipping carriers
  3. Most Favored Customer.  Your largest customer has special requirements for shipping and tracking, and they’re gonna get what they want.  “Thank you sir, may I have another?”  Minor geek points for nailing the movie and actor.
  4. All other domestic and international orders are handled in a generic manner

 

First off, we’ve got an Order class and an abstract OrderHandler class that for the “Chain of Responsibility” handlers.  They look like the following:

 

      public class Order

      {

            private string _countryCode;

            private double _orderAmount;

            private double _customer;

 

            public string CountryCode

            {

                  get { return _countryCode; }

                  set { _countryCode = value; }

            }

 

            public double OrderAmount

            {

                  get { return _orderAmount; }

                  set { _orderAmount = value; }

            }

 

            public double Customer

            {

                  get { return _customer; }

                  set { _customer = value; }

            }

      }

 

      public abstract class OrderHandler

      {

            private OrderHandler _nextHandler;

 

            // Entry point

            public void ProcessOrder(Order order)

            {

                  if (this.CanHandle(order))

                  {

                        this.handleRequest(order);

                  }

                  else

                  {

                        _nextHandler.ProcessOrder(order);

                  }

            }

 

            // Determines if this OrderHandler can handle the order

            public abstract bool CanHandle(Order order);

 

            // Performs the specific actions for the type of order

            protected abstract void handleRequest(Order order);

 

            // Take in an OrderHandler and put it at the very end of the Linked List

            public void AppendSibling(OrderHandler lastHandler)

            {

                  if (_nextHandler == null)

                  {

                        _nextHandler = lastHandler;

                  }

                  else

                  {

                        _nextHandler.AppendSibling(lastHandler);

                  }

            }

      }

 

The OrderHandler implements a linked list structure.  When the ProcessOrder() method is called, an OrderHandler uses its CanHandle() method to determine if it can handle the Order.  If it can handle the Order, it calls its handleRequest() method to process the order and returns.  Otherwise the OrderHandler passes the Order to the next OrderHandler sibling in the chain until some handler can process the Order.  An obvious warning is required here, there needs to be some sort of last resort, default handler at the end of the chain.  So now we can create the specific handlers for the cases we outlined above and the OrderService itself.

 

      public class MostFavoredCompanyHandler : OrderHandler{…}

      public class EuropeanOrderHandler : OrderHandler{…}

      public class LargeOrderHandler : OrderHandler{…}

      public class DefaultOrderHandler : OrderHandler{…}

 

      public class OrderService

      {

            public void ReceiveOrder(Order order)

            {

                  // Do some logging or security or something valuable

                  OrderHandler handler = createHandlerChain();

                  handler.ProcessOrder(order);

            }

 

            // In real life you might pull the nodes in the Chain of Responsibility

            private OrderHandler createHandlerChain()

            {

                  OrderHandler topHandler = new LargeOrderHandler();

                  topHandler.AppendSibling(new EuropeanOrderHandler());

                  topHandler.AppendSibling(new LargeOrderHandler());

                  topHandler.AppendSibling(new MostFavoredCompanyHandler());

                  topHandler.AppendSibling(new DefaultOrderHandler());

 

 

                  return topHandler;

            }

      }

 

OrderService itself can be rapidly extended by creating new OrderHandler subclasses and popping them into the createHandlerChain() method.  It’s an example of the Open/Closed Principle.  The behavior of the system can be altered by either adding handlers or changing the order of the handlers in the chain of responsibility without making any further code modifications to OrderService.  In a very complex system you might use some sort of Plugin pattern infrastructure to add OrderHandler’s through configuration or run time bootstrapping.  As a shameless plug, I did exactly this on a project that used StructureMap to configure a list of translation handlers.

 

From a testability standpoint the CoR pattern can be beneficial because it lets you unit test in smaller chunks.  I purposely left the CanHandle() method accessible as a public method.  When you test really complicated conditional processing logic you can make the unit testing easier by separately testing the decision to do an action from the action itself.  In concrete terms, when we test an OrderHandler class we can write separate, simpler unit tests for CanHandle() and handleRequest(). 

 

Subclasses of OrderHandler override the CanHandle() and handleRequest() abstract methods, but the general workflow is implemented in the abstract superclass.  That’s a textbook example of a Template pattern.  One thing to keep in mind is that patterns often occur together in the same class or cluster of classes.  Another more important thing to remember about design patterns is they’re just things that you do all the time in code, not some kind of new magic.

 

Alternative Implementation

 

I don’t have any kind of CompSci background in “pure” languages like LISP and C++, so linked lists seem weird to me.  I will usually put the possible handlers in an array.  The caller iterates over the array until it finds a handler that can handle the request and executes that handler.  It’s identical in effect, just different.  I think it makes the Plugin mechanics simpler, but that might be the tail wagging the dog.

 

Other Examples of Chain of Responsibility

 

  • Single sign on security solutions for web applications.  You might have a handler to check if the user is already authenticated, another handler to check for windows authentication, and a last handler to transfer the request to a logon page.
  • Last week I worked on a CoR implementation that analyzed exceptions coming back from a messaging component to diagnose the exception for production support.  Eventually this implementation might have handlers to resubmit the request or provide guidance for production support.  The list of handlers will have to be able to grow in the future.
  • The CoR pattern happens pretty frequently in conjunction with Composite structures

 

And How Not to Use Patterns

 

For about 18 months I was by far the youngest guy on a centralized architecture team (think of every bad thing you’ve ever thought or heard about a central architecture team and apply them here).  I took a perverse pleasure in correcting my peers whenever they misused a pattern name.  One day our most senior and highly paid architect was finally showing us his new world order for SOA utopia.  He kept mislabeling his proposed, elaborate architecture for creating all new web services as a “Chain of Responsibility” pattern and I kept telling him that he was wrong (He was really just using some EJB equivalent of chaining IHttpModule’s together in IIS for things like security and logging).  Don’t ever be the pedantic ass or the idiot spouting patterns who’s talking out of his ass.  Then again, it’s awfully fun to verbally abuse beard-stroking, non-coding architects.

 



Comments

ashapochka said:

It may be interesting to note, I've recently reimplemented the Apache Commons chain library (its generic part) in C# and they have the chain's XML configuration built on top of the other Apache Commons libraries, so it would have taken lots of time to reproduce it in C# and I decided to use your StructureMap as a configuration framework instead. I must say the two work together beautifully. Abstract Commands become PluginFamilies and their various implementations and chains become Plugins. The only problem has been your PluginFamilies configured in xml accept a single external memento source XOR embedded mementos and this was unfortunate since StructureMap.config quickly grew cluttered with all kinds of command and chain instance configurations.

I seem to have solved the problem though. I implemented an additional class CompositeMementoSource that holds references to the child MementoSources and delegates to them containsKey and retrieveMemento calls on itself.
So in MementoSourceMapper.ReadFromXml(...) I create an instance of CompositeMementoSource , add all found external XmlFile sources and the EmbeddedMememntoSource to it and then return it for PluginFamily.Source initialization. And that's it. Now I can configure several external memento sources as well as embedded instances within one PluginFamily xml node in StructureMap.config.

I thought it would be great to have this feature in the next StructureMap release.
# November 7, 2005 3:30 AM

breichelt said:

Kevin Bacon, Animal House :)
# November 7, 2005 9:34 AM

Michael said:

Now, what I want to know, Ben, is whether or not you were able to finish reading the post before you responded ;)
# November 7, 2005 6:33 PM

breichelt said:

Michael, No I didnt finish reading before commenting, I had to go back :)
# November 8, 2005 9:28 AM

Jeremy D. Miller said:

Andriy,

Is there any chance you could send me something about what you did? That sounds like something interesting to get into the next version. I have some situations where that would be useful.

# November 10, 2005 9:19 PM

ashapochka said:

Jeremy,

With pleasure! I can send you the relevant sources by email if it's ok with you. Just send me a message on ashapochka at gmail dot com and I will reply with the src for the CompositeMementoSource, Chains and the rest of it. I'd really enjoy having the functionality in the official StructureMap

Andriy.
# November 13, 2005 11:24 PM

Jiho Han said:

First of all, I really enjoy your posts! Keep up the good work.

I am a bit confused though regarding your last paragraph. Isn't chaining multiple IHttpModules in fact an implementation of CoR pattern? Or am I missing something?
# November 16, 2005 1:12 PM

Jeremy D. Miller -- The Shade Tree Developer said:

One of my colleagues asked me to demonstrate and explain six patterns for folks with little or no exposure...
# April 11, 2006 4:12 PM

Nblog said:

Kolejna porcja linków związanych z wzorcami projektowymi. Nie wszystkie jeszcze zdążyłem przeczytać,...
# June 5, 2006 5:03 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Between being extremely short handed at work, tech' reviewing a new book, a
possible book proposal...
# August 7, 2006 4:51 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Between being extremely short handed at work, tech' reviewing a new book, a possible book proposal

# September 1, 2006 2:33 PM

Chain-of-responsibility pattern by example « When IE meets SE said:

Pingback from  Chain-of-responsibility pattern by example « When IE meets SE

# January 5, 2008 5:22 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

Our Sponsors

Free Tech Publications

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP