Chain Of Responsibility Pattern

Intent: 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.

Discussion: The pattern chains the receiving objects together, and then passes any request messages from object to object until it reaches an object capable of handling the message. The number and type of handler objects isn't known a priori, they can be configured dynamically. The chaining mechanism uses recursive composition to allow an unlimited number of handlers to be linked.

Chain of Responsibility simplifies object interconnections. Instead of senders and receivers maintaining references to all candidate receivers, each sender keeps a single reference to the head of the chain, and each receiver keeps a single reference to its immediate successor in the chain.

Make sure there exists a "safety net" to "catch" any requests which go unhandled.

Do not use Chain of Responsibility when each request is only handled by one handler, or, when the client object knows which service object should handle the request.

Example: The Chain of Responsibility pattern avoids coupling the sender of a request to the receiver by giving more than one object a chance to handle the request. Mechanical coin sorting banks use the Chain of Responsibility. Rather than having a separate slot for each coin denomination coupled with a receptacle for the denomination, a single slot is used. When the coin is dropped, the coin is routed to the appropriate receptacle by the mechanical mechanisms within the bank. [Michael Duell, "Non-software examples of software design patterns", Object Magazine, July 1997, p54]

Rules of thumb: Chain of Responsibility, Command Pattern, Mediator Pattern, and Observer Pattern, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers.

Chain of Responsibility can use Command Pattern to represent requests as objects. [GOF, p349]

Chain of Responsibility is often applied in conjunction with Composite Pattern. There, a component's parent can act as its successor. [GOF, p232]


Examples

Apache Jakarta Chain: jakarta.apache.org it is in Java Language

The $PATH environment variable on unix machines.

NetBeans MultiFileSystem www.netbeans.org

"Plan 9 has union directories: directories made of several directories all bound to the same name. The directories making up a union directory are ordered in a list. When the bindings are made (see bind(1)), flags specify whether a newly bound member goes at the head or the tail of the list or completely replaces the list. To look up a name in a union directory, each member directory is searched in list order until the name is found. A bind flag specifies whether file creation is allowed in a member directory: a file created in the union directory goes in the first member directory in list order that allows creation, if any. " plan9.bell-labs.com

The Power Plant framework used (uses?) this pattern to dispatch events from the actual target (button) up to its super-'commanders' (window, application).

Dot Net Remoting uses "sink chains" to implement its remoting channels. On the client side, a method-call message gets passed to a formatter sink, which serializes it to the network format then passes it along to a transport sink that takes care of sending it out to the network. On the server side, an incoming network message is read by the transport sink, which passes it to a formatter sink for deserialization, which passes it to a dispatcher sink which makes the actual method call and then returns the results back though the server chain, the network, and then the client chain. Additional sinks can be inserted between the standard chain elements to provide additional processing (logging, encryption, translation, forwarding, replication, load-balancing, etc.) without requiring any changes to the existing sink or channel implementations.

Axis (ws.apache.org ) Handlers and Chains

Amiga Os "input.device" represented the central clearing house for all input events, including game, mouse, and keyboard-related events. The system's GUI, intuition.library, merely sits on the input.device's handler list as any other program would (albeit at a priority of 50). Screen blankers often detected system-wide events, and UI recorder programs would use input.device to record events as they came through. Accessibility programs would use input.device to synthesize some UI events in response to others.


Note that each node along the chain of responsibility must be able to either directly handle or forward the request. If the "request" is coded directly as, for instance, a C++ method call, then every node along the chain must define that method call, with non-handling nodes merely re-invoking the method on the parent. To avoid having each node define methods for all possible requests, in a static language like C++, requires that a Command pattern be used, where an actual object encapsulates the "request". Note however that using a command object to pass around requests on the chain of responsibility is less efficient than using the language's built in command mechanism (i.e. direct method invocation), because command parameters (i.e. method arguments) must then be manually encoded by the sender, passed along the chain, and decoded at the receiver.

This is a difficult tradeoff between syntactic conciseness and execution speed (using the language's built in method invocation) on the one hand, and class bloat on the other hand (requiring each class along the chain to support all message types).

If requests don't need to follow arbitrarily long chains of responsibility, a better pattern to use might be Mediator, so that only the mediator node needs to know about all possible requests coming from its child nodes, and these requests could be coded as native language methods, affording clarity and speed. No other nodes in the entire system need to be "polluted" with these only locally-relevant methods. In other words, the Mediator abstracts communication by being the central hub, so only it needs know about all messages. The Chain Of Responsibility abstracts communication by passing a message along a chain; but in a static language like C++ the "passing" of an anonymous "message" requires use of a less efficient Command pattern, or support in all nodes for all message types (in which case the messages are no longer "anonymous")..


From my point of view, this pattern also seems to say why Exceptions Are Our Friends. Run-time errors, or exceptions, are realised in a module, and that module should raise the error to its caller. But in turn, the caller should then raise the same exception to its caller, giving each parent the chance to handle the exception, before terminating the application. One of the reasons why writing decent error handling routines in languages like Visual Basic is so difficult. -- Matt Ryall

Concur. Hardware control is pretty much designed this way. Unless there is a completely predictive way to handle a particular hardware error you gotta inform the caller that the widget under control has failed in some way. The decision on what to do about the failure is put off to the very highest level you can get away with. In process automation it typically ends up firing an alarm for an operator to deal with.


Ahem. Isn't class inheritance in Object Oriented Languages such as Java Language and Smalltalk Language a more common application of this pattern? When a method is called on an object, the method dispatch system first tries to find the method on the object being called, then on it's parent, etc. on up the tree.

Not totally. Inheritance functions more like a message broker. The runtime locates a function to call and calls it. Chain of Responsibility functions more like a message bus. Each receiving object is given a chance to handle the message or pass it along. Inheritance can be made to function in this way by using "base" or "super" calls, but it is not as natural a fit as separate handler classes and it constrains the inheritance tree. -- David Sidlinger


How can we deal with explosion of classes when using Chain Of Responsibility? -- Bala Paranj

This is not a problem. The decision of being responsible for the handling of a request is made per object, not per class. So you could have an arbitrary number of objects in the chain, all of the same class, while handling different requests. If different classes are necessary, they would be necessary anyways, Chain Of Responsibility or not. -- Timo Reitz


Is it not that "non-resumptive exception handling" in modern object oriented languages, like C++ and Java, follow Chain Of Responsibility Pattern pattern? When an exception is thrown, the exception handlers are looked-up for a match. The exception object is passed till a matching handler is found. So, can it be assumed that exception handling follows Chain Of Responsibility Pattern? - S G Ganesh

The sender is decoupled from the receiver, certainly, but there is no explicit instance of the pattern. Who needs a pattern when you have a feature? (Design Patterns Are Missing Language Features).


To paraphrase Malcolm Reynolds - "Do you know what the chain of responsibilty is here? It's the chain I go get and beat you with to show you who's responsible."


I have always wondered why GOF says that the successor would be the parent node when combining CoR with Composite. It has always been more natural to me to think of the children nodes as the successor, or is this because I am locked into a "Decision Tree" paradigm? - Francis Anderson


I see this pattern as a design-oriented if-then-else statement. When I am tempted to write a long string of if and else clauses with anything but trivial conditions or one-line bodies, I first look to this pattern to see if it will help clean up the code. - Skip Sailors


See original on c2.com