Chain Of Responsibility Pattern

July 11, 2008

one comment

Chain Of Responsibility Pattern

Today’s post will introduce the chain of responsibility pattern.
You can read my previous posts about design patterns here:
Structural patterns
Decorator pattern 
Proxy pattern
Facade pattern
Adapter pattern
Composite pattern
Bridge pattern
Flyweight pattern

Creational patterns
Singleton pattern
Abstract Factory pattern
Prototype pattern
Factory Method pattern
Builder pattern

Behavioral Patterns
Strategy pattern
Iterator pattern 
Template method pattern
Command pattern

Chain of Responsibility Pattern
The chain of responsibility pattern is a way of communication
between objects. As it’s name indicate a chain of handlers is built 
and every handler in the chain is responsible to handle the passing
request or deliver it to the next handler in the chain. In the end of
the process the request is handled with a default or exceptional behavior.
The pattern helps to reduce coupling by freeing the object from knowing
which handler will handle the request in the end.
 
Use Cases for the Chain of Responsibility Pattern
 
You should use the pattern in the following cases:

  • You have more than one object that may handle a request.
  • You have a scenario that you need to pass a request to
    one of several objects without specifying the receiver.
  • You have handlers of a request that should be specified
    dynamically.

UML Diagram 
Chain of Responsibility UML

Example in C#

    #region Abstract Handler Class

    public abstract class Handler

    {

        #region Properties

        /// <summary>

        /// The request limit that the current handler

        /// can process

        /// </summary>

        public int RequestLimit { get; private set; }

        /// <summary>

        /// The next handler in the chain

        /// </summary>

        public Handler NextHandler { get; private set; }

        #endregion

        #region Methods

        public abstract void HandleRequest(int request);

        #endregion

        #region Ctor

        public Handler(Handler handler, int requestLimit)

        {

            NextHandler = handler;

            RequestLimit = requestLimit;

        }

        #endregion

    }

    #endregion

    #region Concrete Handlers

    public class Worker : Handler

    {

        #region Ctor

        /// <summary>

        /// Construct a new worker object with

        /// the given handler

        /// </summary>

        /// <param name="handler">The given handler</param>

        public Worker(Handler handler)

            : base(handler, 10000)

        {

        }

        #endregion

        #region Methods

        public override void HandleRequest(int request)

        {

            if (request < RequestLimit)

            {

                Console.WriteLine("{0} handled a {1} request",

                    GetType().Name, request);

            }

            else

            {

                if (NextHandler != null)

                {

                    NextHandler.HandleRequest(request);

                }

            }

        }

        #endregion

    }

    public class Manager : Handler

    {

        #region Ctor

        /// <summary>

        /// Construct a new manager object with

        /// the given handler

        /// </summary>

        /// <param name="handler">The given handler</param>

        public Manager(Handler handler)

            : base(handler, 20000)

        {

        }

        #endregion

        #region Methods

        public override void HandleRequest(int request)

        {

            if (request < RequestLimit)

            {

                Console.WriteLine("{0} handled a {1} request",

                    GetType().Name, request);

            }

            else

            {

                if (NextHandler != null)

                {

                    NextHandler.HandleRequest(request);

                }

            }

        }

        #endregion

    }

    public class SeniorManager : Handler

    {

        #region Ctor

        /// <summary>

        /// Construct a new senior manager object with

        /// the given handler

        /// </summary>

        /// <param name="handler">The given handler</param>

        public SeniorManager(Handler handler)

            : base(handler, 50000)

        {

        }

        #endregion

        #region Methods

        public override void HandleRequest(int request)

        {

            if (request < RequestLimit)

            {

                Console.WriteLine("{0} handled a {1} request",

                    GetType().Name, request);

            }

            else

            {

                if (NextHandler != null)

                {

                    NextHandler.HandleRequest(request);

                }

            }

        }

        #endregion

    }

    #endregion

The example is simple. I have three types of workers: worker,
manager and a senior manager. Every worker type can handle request
that are lower than the request limit they have. Whenever a request
that is bigger than the request limit arrives the worker type deliver the
request to the next handler in the chain until there is no one who can
handle the request. The following example shows a use case of the example
classes:

    class Program

    {

        static void Main(string[] args)

        {

            // Setup Chain of Responsibility

            SeniorManager seniorManager = new SeniorManager(null);

            Manager manager = new Manager(seniorManager);

            Worker worker = new Worker(manager);

            // Run requests along the chain

            worker.HandleRequest(5000);

            worker.HandleRequest(15000);

            worker.HandleRequest(35000);

            Console.WriteLine();

            manager.HandleRequest(5000);

            manager.HandleRequest(15000);

            manager.HandleRequest(35000);

            Console.WriteLine();

            seniorManager.HandleRequest(5000);

            seniorManager.HandleRequest(15000);

            seniorManager.HandleRequest(35000);

            // Wait for user

            Console.Read();

        }

    }

Summary
To sum up the post, the chain of responsibility pattern isn’t
commonly used. Even so it’s very helpful if you want to send a
request along a chain of objects that may or may not handle the
request. In the next post in this series I’ll explain the mediator
pattern

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

one comment

  1. plpastaAugust 26, 2008 ב 7:42

    Hi. In case you would need generic, ready-to-use CoR implementation for .NET or Mono you can try this: http://nchain.sourceforge.net . I’ll appreciate any feedback :) Cheers, P.

    Reply