Chain Of Responsibility Design Pattern

HTML clipboard

Definition

GoF -> A way of passing a request between a chain of objects

  1. The Chain of Responsibility pattern works with a list of Handler objects that have limitations on the nature of the requests they can deal with. If a handler object cannot handle a request, it passes it on to the next handler object in the chain. At the end of the chain, there can be either default or exceptional behavior.

  2. The pattern chains the receiving objects together, and then passes any request messages from object to object until it reaches an object capable of handling the message.

  3. Chain of Responsibility simplifies object interconnections. Instead of senders and receivers maintaining references to all candidate receivers, each sender keeps a single reference to the head of the chain, and each receiver keeps a single reference to its immediate successor in the chain.

  4. Sometimes, the request object has to go through the chain objects mandatorily, like Http pipeline.

  5. Sometimes only through few handlers.

Design

Let us take an example; we are conducting a GK context. We have three teams to answer the questions. Each team will have 10000 ms to answer the questions, and team one has to start the each question. If team one didn't answer the question, it will be passed on to the next team.

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

UML Diagram

From GoF

chain1.gif

chain2.gif

Code

---------------- handler Base class ----------------------
public abstract class Handlerbase
    {
        public Handlerbase NextTeam { get; private set; }
        public ContextObject Question { get; private set; }

        public Handlerbase(Handlerbase nextHandler, ContextObject question)
        {
            NextTeam = nextHandler;
            Question = question;
        }

        public abstract void HandleRequest();
    }

    ---------------- queue object one ----------------------

public class TeamOne: Handlerbase
    {
        public TeamOne(Handlerbase nextHandler, ContextObject question) : base(nextHandler, question) { }

        public override void HandleRequest()
        {
            Console.WriteLine("Question : {0}", Question.Question.ToString());
            Console.WriteLine("*******************************************"));

            Console.WriteLine("Wating for team one to respond");
            Thread.Sleep(10000);
            Console.WriteLine("\t no response from team one.....");

            NextTeam.HandleRequest();
        }
    }

    ---------------- chain object two ----------------------

    public class TeamTwo : Handlerbase
    {
        public TeamTwo(Handlerbase nextHandler, ContextObject question) : base(nextHandler, question) { }

        public override void HandleRequest()
        {
            Console.WriteLine("Wating for team two to respond");

            Thread.Sleep(10000);

            Console.WriteLine("\t no response from team two.....");
            NextTeam.HandleRequest();
        }
    }

    ---------------- chain object tree ----------------------

    public class TeamThree : Handlerbase
    {
        public TeamThree(Handlerbase nextHandler, ContextObject question) : base(nextHandler, question) { }

        public override void HandleRequest()
        {
            Console.WriteLine("Wating for team three to respond");
            Thread.Sleep(10000);
            Console.WriteLine("\t no response from team three as well .....");
        }
    }

    ---------------- Request----------------------
    public class ContextObject
    {
        public string Question { get; set; }
    }
   ---------------- Client----------------------
        static void Main(string[] args)
        {
            ContextObject question = new ContextObject() { Question = "Who is an ediat in your team?" };

            TeamThree teamThree = new TeamThree(null, question);
            TeamTwo teamTwo = new TeamTwo(teamThree, question);
            TeamOne teamOne = new TeamOne(teamTwo, question);

            teamOne.HandleRequest();
            Console.ReadKey();
        }