Chain Of Responsibility Pattern

 Rate It (2)

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

Revision number 2, Friday, October 03, 2008 8:27:10 PM by gilfink

Comments

Related Articles

Design Patterns

Design Patterns Design patterns are recognized solutions to common problems defined originally by the Gang of Four programmers. Design patterns are used throughout the ASP.NET Framework. The various patterns are commonly divided into several different groups

Prototype Pattern

The prototype is built upon the use of object cloning. The prototype creates new objects by cloning one of its concrete classes. The prototype is used in the following situations: You need to hide the concrete product classes from the client. You want to reduce

Threat Modeling

It's absolutely necessary if you're serious about security. Whitepapers/Books/Blogs Threat Modeling for ASP.NET (PDF) - an excellent white paper from Rüdiger Grimm and Henrik Eichstädt from the University of Kent Threat Modeling book from MSPress

IDisposable Pattern

The IDisposable pattern isn't one of the a classic patterns. It's a pattern suggested in MSDN to implement the IDisposable interface. You should be familiar with the pattern or with the interface because it's a basic thing to know about the .Net

Shortcuts

Table of Contents

Top Wiki Contributors

(last 30 days)

  1. mbanavige (7)
  2. yrb.yogi (5)
  3. srinivaskotra (3)
  4. XIII (2)
  5. rdmartin33 (2)
  6. Babunareshnarra (2)
  7. Dungimon (1)
  8. ali62b (1)
Microsoft Communities