65.9K
CodeProject 正在变化。 阅读更多。
Home

责任链设计模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (33投票s)

2009年8月26日

CPOL

3分钟阅读

viewsIcon

70982

downloadIcon

411

本文展示了一个关于如何使用责任链设计模式的案例研究。

背景

再次来到我最喜欢的地方 - 伊丽莎白的日托中心。

在我的家庭中,我和我的妻子都需要每天工作;因此,我们每天早上8点到下午5点把孩子送到日托中心。我在之前的文章中也使用了我女儿的日托中心作为示例场景。

在伊丽莎白的日托中心,使用1-888-8888-8888的号码来接听所有关于任何请求的电话。

为了处理请求,前台的老师会首先接电话;她需要决定她是否能处理该请求,如果需要上级做出决定,则将请求推给她的主管。

本案例研究中可以使用三种类型的请求

  1. 父母要求获得孩子每日状态的副本。(此请求可以由老师自己处理。)
  2. 父母要求支付学费。(此请求需要由老师的经理解释。)
  3. 王博士要求为所有孩子安排一次访问。(此请求需要得到主任的批准。)

请记住,所有请求都从拨打888号码开始,前台老师接听电话并确定她是否可以处理该请求。

引言

责任链模式描述了我们如何通过一系列多个处理程序对象来处理单个请求。该请求必须仅由该链中的一个处理程序对象处理。但是,处理请求的决定由当前处理程序决定。如果当前处理程序对象能够处理请求,则将在当前处理程序对象中处理该请求;否则,当前处理程序对象需要放弃责任并将请求推送到下一个链处理程序对象。依此类推,直到处理完请求为止。

责任链设计模式结构

Chain.JPG

类图

实现代码

处理程序对象

员工

Staff 类是我们的抽象处理程序基类。它在这里定义了公共函数 (ProcessRequest),以允许子类实现细节。在这个类中,声明了一个StaffBoss)对象来实现我们的责任链。

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 类中,我实际上编写了代码来决定老师可以处理哪种类型的请求。例如:如果请求级别不是 Low,则老师需要将请求推给她的老板进行审查。

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);
                }
            }
        }
    }
}

管理器

它是一个从 Staff 继承的子类。它有自己的条件来检查请求是否可以被处理或被推给她的老板。

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 类与 TeacherManager 类相同。在本案例研究中,它将用作链的末尾。

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 类是一个辅助类,用于保存此演示的请求信息。

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

客户端应用程序

从客户端来看,我为 TeacherManagerDirector 分别创建了一个对象。我还构建了责任链来处理来自客户端的不同请求(Teacher --> Manager --> Director)。

从客户端来看,我还创建了三个请求并发送给老师进行筛选。每个请求都有不同的级别,这将决定谁是处理请求的正确处理程序。

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();

            }
        }
    }
}

一旦你运行客户端应用程序,所有相应的处理程序都将拾取正确的请求开始处理。酷!

Chain_Output.JPG

结论

在本文中,我演示了如何使用责任链模式来实现日托请求系统。我还在另一篇文章中使用了日托中心场景来实现 策略设计模式

© . All rights reserved.