Chain-of-responsibility pattern
From Wikipedia, the free encyclopedia
In Object Oriented Design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains a set of logic that describes the types of command objects that it can handle, and how to pass off those that it cannot to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain.
In a variation of the standard chain-of-responsibility model, some handlers may act as dispatchers, capable of sending commands out in a variety of directions, forming a tree of responsibility. In some cases, this can occur recursively, with processing objects calling higher-up processing objects with commands that attempt to solve some smaller part of the problem; in this case recursion continues until the command is processed, or the entire tree has been explored. An XML interpreter (parsed, but not yet executed) might be a fitting example.
This pattern promotes the idea of loose coupling, which is considered a programming best practice.
[edit] Examples
The following Java code illustrates the pattern with the example of a logging class. Each logging handler decides if any action is to be taken at this log level and then passes the message on to the next logging handler. The output is:
Writing to stdout: Entering function y. Writing to stdout: Step1 completed. Sending via e-mail: Step1 completed. Writing to stdout: An error has occurred. Sending via e-mail: An error has occurred. Writing to stderr: An error has occurred.
Note that this example should not be seen as a recommendation to write logging classes this way.
Also, note that in a 'pure' implementation of the chain of responsibility pattern, a logger would not pass responsibility further down the chain after handling a message. In this example, a message will be passed down the chain whether it is handled or not.
import java.util.*; abstract class Logger { public static int ERR = 3; public static int NOTICE = 5; public static int DEBUG = 7; protected int mask; // The next element in the chain of responsibility protected Logger next; public Logger setNext( Logger l) { next = l; return l; } public void message( String msg, int priority ) { if ( priority <= mask ) { writeMessage( msg ); } if ( next != null ) { next.message( msg, priority ); } } abstract protected void writeMessage( String msg ); } class StdoutLogger extends Logger { public StdoutLogger( int mask ) { this.mask = mask; } protected void writeMessage( String msg ) { System.out.println( "Writing to stdout: " + msg ); } } class EmailLogger extends Logger { public EmailLogger( int mask ) { this.mask = mask; } protected void writeMessage( String msg ) { System.out.println( "Sending via email: " + msg ); } } class StderrLogger extends Logger { public StderrLogger( int mask ) { this.mask = mask; } protected void writeMessage( String msg ) { System.err.println( "Sending to stderr: " + msg ); } } public class ChainOfResponsibilityExample { public static void main( String[] args ) { // Build the chain of responsibility Logger l,l1; l1 = l = new StdoutLogger( Logger.DEBUG ); l1 = l1.setNext(new EmailLogger( Logger.NOTICE )); l1 = l1.setNext(new StderrLogger( Logger.ERR )); // Handled by StdoutLogger l.message( "Entering function y.", Logger.DEBUG ); // Handled by StdoutLogger and EmailLogger l.message( "Step1 completed.", Logger.NOTICE ); // Handled by all three loggers l.message( "An error has occurred.", Logger.ERR ); } }
[edit] See also
[edit] External links
- Article "The Chain of Responsibility pattern's pitfalls and improvements" by Michael Xinsheng Huang
- Article "Follow the Chain of Responsibility" by David Geary
- Article "Pattern Summaries: Chain of Responsibility" by Mark Grand
- CoR overview
- Behavioral Patterns - Chain of Responsibility Pattern
- Descriptions from Portland Pattern Repository
- Apache Jakarta Commons Chain
- PerfectJPattern Open Source Project, Provides a context-free and type-safe implementation of the Chain of Responsibility Pattern in Java
- Chain.NET(NChain) - Ready-to-use, generic and lightweight implementation of the Chain of Responsibility pattern for .NET and Mono
|