Chain of Responsibility Design Pattern

In Chain of Responsibility pattern, we create a chain of objects which handles a particular request. Each object contains a reference to his next object, if the object does not want to handle the request, it’s simply forward the request to next object handler. When a object is ready for handling the request, it’s does not forward the request to next object.

We use chain of responsibility pattern when we have more than one object to handle a request, but we don’t know in advance which object handle the request until run-time.

Structure of Chain of Responsibility pattern

Chain Of Responsibility Pattern

In the above diagram, we have an IHandler interface. This interface contains a single method HandleRequest(). This interface must be implemented by all the objects which are in the request handling chain. Each object also contains a handler variable of IHandler type which references the next object in the chain.

Example

ChainOfResponsibility-Pattern-Example

In this example, I have created a IProblemHandler interface which has a single method named HandleRequest. In the chain, we have three objects Employee, Manager, and TechArch all implemented the IProblemHandler interface. Employee contains a reference to the Manager. Manager contains a reference to the TechArch. Each object don’t know about which reference it is taking. Each object stores reference into the IProblemhandler object named ‘nextHandler’.

First request comes to the Employee. If employee can not handle the request, then the Employee forward the request to the Manager. If Manager also can not handle the request, then the request go to the TechArch.

Below is the example in C# code.


    class Program
    {
        static void Main(string[] args)
        {
            TechArch techArch = new TechArch(null);
            Manager manager = new Manager(techArch);
            Employee employee = new Employee(manager);

            employee.HandleRequest(45); //Request will handle by Tech Arch
            employee.HandleRequest(15); //Request will handle by Manager
            employee.HandleRequest(8); //Request will handle by Employee
        }
    }

    public interface IProblemHandler
    {
        void HandleRequest(int problemID);
    }

    public class Employee : IProblemHandler
    {
        IProblemHandler nextHandler;

        public Employee(IProblemHandler nextHandler)
        {
            this.nextHandler = nextHandler;
        }

        public void HandleRequest(int problemID)
        {
            if (problemID > 0 && problemID <= 10)
            {
                Console.WriteLine("Employee handles the request");
            }
            else if (this.nextHandler != null)
            {
                this.nextHandler.HandleRequest(problemID);
            }
        }
    }

    public class Manager : IProblemHandler
    {
        IProblemHandler nextHandler;

        public Manager(IProblemHandler nextHandler)
        {
            this.nextHandler = nextHandler;
        }

        public void HandleRequest(int problemID)
        {
            if (problemID >= 11 && problemID <= 20)
            {
                Console.WriteLine("Manager handles the request");
            }
            else if (this.nextHandler != null)
            {
                this.nextHandler.HandleRequest(problemID);
            }
        }
    }

    public class TechArch : IProblemHandler
    {
        IProblemHandler nextHandler;

        public TechArch(IProblemHandler nextHandler)
        {
            this.nextHandler = nextHandler;
        }

        public void HandleRequest(int problemID)
        {
            if (problemID >= 21)
            {
                Console.WriteLine("Technical Architect handles the request");
            }
            else if (this.nextHandler != null)
            {
                this.nextHandler.HandleRequest(problemID);
            }
        }
    }