Click here to Skip to main content
15,883,772 members
Articles / Programming Languages / C#

Chain Of Responsibility Pattern

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
20 Oct 2013CPOL1 min read 11.3K   5   1
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

This articles was originally at wiki.asp.net but has now been given a new home on CodeProject. Editing rights for this article has been set at Bronze or above, so please go in and edit and update this article to keep it fresh and relevant.

Introduction

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

Image 1

Example in C#

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:

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
The ASP.NET Wiki was started by Scott Hanselman in February of 2008. The idea is that folks spend a lot of time trolling the blogs, googlinglive-searching for answers to common "How To" questions. There's piles of fantastic community-created and MSFT-created content out there, but if it's not found by a search engine and the right combination of keywords, it's often lost.

The ASP.NET Wiki articles moved to CodeProject in October 2013 and will live on, loved, protected and updated by the community.
This is a Collaborative Group

754 members

Comments and Discussions

 
QuestionImage was missing Pin
Tridip Bhattacharjee9-Oct-14 20:55
professionalTridip Bhattacharjee9-Oct-14 20:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.