Click here to Skip to main content
Licence CPOL
First Posted 26 Aug 2009
Views 16,063
Downloads 111
Bookmarked 50 times

Chain of Responsibility Design Pattern

By | 26 Aug 2009 | Article
This article shows a case study about how we can use the Chain of Responsibility Design Pattern.

Background

Again, my favorite place - Elizabeth's daycare center.

In my family, my wife and I both need to work everyday; therefore, we drop our kids to the daycare center from 8:00 am to 5:00 pm. I have used my daughter's daycare center as an example scenario in my other articles as well.

In Elizabeth's daycare center, a 1-888-8888-8888 number is used to take all the calls regarding any requests.

To process a request, the teacher in the front desk will answer the phone first; she needs to make the decision whether she can handle the request or not, pushing the request to her supervisor if the decision needs to be made from the upper level.

Three types of requests could be used in this case study:

  1. The parent requests to have a copy of their kid's daily status. (This request can be handled by the teacher herself.)
  2. The parent requests to pay the tuition. (This request needs to be explained by the teacher's manager.)
  3. Dr. WANG requests to schedule a visit for all the kids. (This request needs to be approved by the director.)

Remember, all the requests start by calling the 888 numbers, the front desk teacher takes the call and determines if she could process the request.

Introduction

The Chain of Responsibility Pattern describes how we handle a single request by a chain of multiple handler objects. The request has to be processed by only one handler object from this chain. However, the determination of processing the request is decided by the current handler. If the current handler object is able to process the request, then the request will be processed in the current handler object; otherwise, the current handler object needs to shirk responsibility and push the request to the next chain handler object. And so on and so forth until the request is processed.

Chain of Responsibility Design Pattern Structure

Chain.JPG

Class Diagram

Implementation Code

Handler Objects

Staff

The Staff class is our base abstract handler class. It defines the common function (ProcessRequest) here to allow the child class to implement the details. In this class, a Staff (Boss) object is declared to implement our Responsibility Chain.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace ChainResponsibility
    {
        //base handler
        public abstract class Staff
        {
            public string Name { get; set; }
            public Staff Boss { get; set; }
            public abstract void ProcessRequest(Request aRequest);           
        }
    }
}

Teacher

In my Teacher class, I actually code the condition to decide what type of request the teacher can handle. For example: if the request level is not Low, the teacher needs to push the request to her boss to review it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace ChainResponsibility 
    {
        public class Teacher : Staff 
        {

            public override void ProcessRequest(Request aRequest)
            {
                if (aRequest.Level != ResponsiableLevel.Low)
                {
                   
                    
                    if (Boss != null)
                    {
                      Console.WriteLine("This is {0}. I am a teacher of this daycare." + 
                         " I am not able to process your request. " + 
                         "My boss {1} will review your request", 
                         this.Name, Boss.Name);
                        Boss.ProcessRequest(aRequest);
                    }
                    else
                        throw new NullReferenceException("No boss assigned");
                }
                else
                {
                    Console.WriteLine("This is {0}. I am a teacher of this " + 
                       "daycare. Your request has been approved!", this.Name);
                }
            }
        }
    }
}

Manager

It is a child class that inherits from Staff. It has its own condition to check if a request can be processed or be pushed to her boss.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace ChainResponsibility
    {
        public class Manager : Staff 
        {
            public override void ProcessRequest(Request aRequest)
            {
                if (aRequest.Level != ResponsiableLevel.Medium)
                {


                    if (Boss != null)
                    {
                        Console.WriteLine("This is {0}. I am a manager of this daycare." + 
                           " Sorry, I am not able to process your request. " + 
                           "My boss {1} will reivew your request", this.Name, Boss.Name);
                        Boss.ProcessRequest(aRequest);
                    }
                    else
                        throw new NullReferenceException("No boss assigned");
                }
                else
                {
                    Console.WriteLine("This is {0}. I am a manager of " + 
                      "this daycare. Your request has been approved!", this.Name);
                }
            }
        }
    }
}

Director

The Director class is the same as the Teacher and Manager classes. It will be used as the end of the chain in this case study.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace ChainResponsibility
    {
        public class Director : Staff 
        {
            public override void ProcessRequest(Request aRequest)
            {
                
                if (aRequest.Level != ResponsiableLevel.High)
                {

                    if (Boss != null)
                    {
                        Console.WriteLine("This is {0}. I am a director of this daycare. " + 
                          "I am not able to process your request. " + 
                          "My boss {1} will reivew your request", this.Name, Boss.Name);

                        Boss.ProcessRequest(aRequest);
                    }
                    else
                        throw new NullReferenceException("No boss assigned");
                }
                else
                {
                    Console.WriteLine("This is {0}. I am a director of this " + 
                      "daycare. Your request has been approved!", this.Name);
                }
            }
        }
    }
}

Request

The Request class is a helper class that holds the request information for this demo.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace ChainResponsibility
    {       
        public class Request
        {
            public ResponsiableLevel  Level { get; set; }
            public string Description { get; set; }
        }

        //Helper Enum
        public enum ResponsiableLevel
        {
            Low,
            Medium,
            High
        }
    }
}

Client App

From the client side, I create an object each for Teacher, Manager, and Director. I also build the responsibility chain to handle the different requests from the client (Teacher --> Manager --> Director).

From the client side, I also create the three requests and send to the teacher for the screening. Each request has the different levels that will decide who will be the correct handler to process a request.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using www.askbargains.com.ChainResponsibility;


namespace www.askbargains.com
{
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                //create a teacher
                Teacher aTeacher = new Teacher();
                aTeacher.Name = "Megan";

                //create a manager
                Manager aManager = new Manager();
                aManager.Name = "Susan";

                //create a director
                Director aDirector = new Director();
                aDirector.Name = "Lisa";

                //create the Organizational Chart. (This is Resposiable Chain)
                aTeacher.Boss = aManager;
                aManager.Boss = aDirector;

                //create a request that can be handled by teacher.
                Request firstRequest = new Request();
                firstRequest.Description = "The parent requests " + 
                   "to have a copy of their kid's daily status";
                firstRequest.Level = ResponsiableLevel.Low;
                Console.WriteLine("Request Info: " + firstRequest.Description);
                //send request
                aTeacher.ProcessRequest(firstRequest);
                Console.WriteLine();

                //create a request that can be handled by manager.
                Request secondRequest = new Request();
                secondRequest.Description = "The parent requests to pay the tuition";
                secondRequest.Level = ResponsiableLevel.Medium;
                Console.WriteLine("Request Info: " + secondRequest.Description);
                //send request
                aTeacher.ProcessRequest(secondRequest);
                Console.WriteLine();

                //create a request that can be handled by teacher.
                Request thirdRequest = new Request();
                thirdRequest.Description = 
                  "Dr. WANG requests to schedule a visit for all the kids";
                thirdRequest.Level = ResponsiableLevel.High ;
                Console.WriteLine("Request Info: " + thirdRequest.Description);
                //send request
                aTeacher.ProcessRequest(thirdRequest);

                Console.ReadLine();

            }
        }
    }
}

Once you run the client app , all the correspondent handlers will pick up the right request to start processing. Cool!

Chain_Output.JPG

Conclusion

In this article, I demonstrated how we can use the Chain of Responsibility Pattern to achieve the implementation for a Daycare Request System. I also used the daycare center scenario for the Strategy Design Pattern in my other article.

License

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

About the Author

SmartAllen

Architect
ICC - (Nationwide Finanical)
United States United States

Member

Sr Software Engineer.Microsoft Certified Solutions Developer (MCSD). owner of www.askbargains.com.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Questionvery nice PinmemberCIDev6:55 24 Feb '12  
GeneralMy vote of 5 PinmemberLucian-aSterX0:02 23 Feb '11  
GeneralGood explanation. Pinmemberccpptrain17:52 29 Sep '10  
GeneralMy comment PinmemberKeithAMS3:32 2 Sep '09  
GeneralRe: My comment PinmemberSmartAllen4:02 2 Sep '09  
GeneralThanks Pinmemberjarimba22:13 31 Aug '09  
GeneralNice article PinmemberVivek_Minhas20:36 27 Aug '09  
Generalnice job Pinmemberuwspstar200915:54 27 Aug '09  
Generalgood PinmemberMember 46629090:16 27 Aug '09  

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

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 26 Aug 2009
Article Copyright 2009 by SmartAllen
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid