本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8109100.html,记录一下学习过程以备后续查用。

    一、引言

    今天我们要讲行为型设计模式的第八个模式--职责链模式。让我们看看现实生活中某公司采购流程的例子吧,理解起来可能更容易。某公司的规章制度规定,采购原材料的总价在5万之内,只需要经理级别的人批准即可;采购总价大于5万小于10万的则需要财务经理进行批准;总价大于10万小于30万的需要总经理批准;总价大于30万的则需要通过董事会会议讨论决定。对于这样一个需求,最直接的方法就是设计一个方法,该方法接受的参数是采购的总价,然后在这个方法内对价格进行判断,然后针对不同的条件交给不同级别的角色去处理。如果情况就是这样,不变了,这样做很好,没问题。如果我们又有新的条件要增加该怎么办呢?我们不得不去修改原来设计的方法来再添加一个条件判断,让本已多重的if-else判断语句更多了,这样的设计显然违背了“开闭原则”。这时候,我们可以采用职责链模式来解决这样的问题。

    二、职责链模式介绍

    职责链模式:英文名称--Chain of Responsibility Pattern;分类--行为型。

    2.1、动机(Motivate)

    在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合。如何使请求的发送者不需要指定具体的接受者,让请求的接受者自己在运行时决定来处理请求,从而使两者解耦。

    2.2、意图(Intent)

    避免请求发送者与接收者耦合在一起,让多个对象都有可能接受请求,将这些对象连接成一条链,并且沿着这条链传递请求,知道有对象处理它为止。——《设计模式》GoF

    2.3、结构图(Structure)

C#设计模式学习笔记:(20)职责链模式

    2.4、模式的组成

    可以看出,在职责链模式的结构图有以下角色:

    1)抽象处理者角色(Handler):抽象处理者定义了一个处理请求的接口,它一般设计为抽象类。由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。因为每一个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个自类型的对象,作为其对下家的引用。通过该引用,处理者可以连成一条链。

    2)具体处理者角色(ConcreteHandler):具体处理者是抽象处理者的子类,它可以处理用户请求。在具体处理者类中实现了抽象处理者中定义的抽象处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限?如果可以处理请求就处理它,否则将请求转发给后继者。在具体处理者中可以访问链中下一个对象,以便请求的转发。

    2.5、职责链模式的具体实现

    在现实生活中,职责链模式的例子也是很多的,例如:公司的请假流程就是一个很好的职责链模式的例子。如果请假半天,只要告诉本部门经理就可以了;如果请假7天或者以上必须人事总监批准;如果请假15天以上,那就要经过总裁批准了。还有类似的例子就是采购的流程,其流程也是职责链模式很好的体现,采购金额的不同,需要批准的人员也不同。下面就以采购的实例来说明职责链模式,实现代码如下:

C#设计模式学习笔记:(20)职责链模式
    class Program
    {
        /// <summary>
        /// 采购请求
        /// </summary>
        public sealed class PurchaseRequest
        {
            //金额
            public double Amount { get; set; }

            //产品名字
            public string ProductName { get; set; }

            public PurchaseRequest(double amount, string productName)
            {
                Amount = amount;
                ProductName = productName;
            }
        }

        /// <summary>
        /// 抽象审批人--相当于“抽象处理者角色”
        /// </summary>
        public abstract class Approver
        {
            //下一位审批人,由此形成一条链。
            public Approver NextApprover { get; set; }

            //审批人的名称
            public string Name { get; set; }

            public Approver(string name)
            {
                Name = name;
            }

            //处理请求
            public abstract void ProcessRequest(PurchaseRequest request);
        }

        /// <summary>
        /// 部门经理--相当于“具体处理者角色”
        /// </summary>
        public sealed class Manager : Approver
        {
            public Manager(string name) : base(name) { }

            public override void ProcessRequest(PurchaseRequest request)
            {
                if (request.Amount <= 10000.0)
                {
                    Console.WriteLine("部门经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);
                }
                else if (NextApprover != null)
                {
                    Console.WriteLine("部门经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);
                    NextApprover.ProcessRequest(request);
                }
            }
        }

        /// <summary>
        /// 财务经理--相当于“具体处理者角色”
        /// </summary>
        public sealed class FinancialManager : Approver
        {
            public FinancialManager(string name) : base(name) { }

            public override void ProcessRequest(PurchaseRequest request)
            {
                if (request.Amount > 10000.0 && request.Amount <= 50000.0)
                {
                    Console.WriteLine("财务经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);
                }
                else if (NextApprover != null)
                {
                    Console.WriteLine("财务经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);
                    NextApprover.ProcessRequest(request);
                }
            }
        }

        /// <summary>
        /// 总裁--相当于“具体处理者角色”
        /// </summary>
        public sealed class CEO : Approver
        {
            public CEO(string name) : base(name) { }

            public override void ProcessRequest(PurchaseRequest request)
            {
                if (request.Amount > 50000.0 && request.Amount < 300000.0)
                {
                    Console.WriteLine("总裁{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);
                }
                else
                {
                    Console.WriteLine("这个采购计划的金额比较大,需要董事会会议讨论才能决定。");
                }
            }
        }

        static void Main(string[] args)
        {
            #region 职责链模式
            PurchaseRequest requestDao = new PurchaseRequest(9000.0, "单刀5把");
            PurchaseRequest requestHuaJi = new PurchaseRequest(40000.0, "10把方天画戟");
            PurchaseRequest requestJian = new PurchaseRequest(90000.0, "5把金丝龙鳞闪电劈");

            Approver manager = new Manager("黄飞鸿");
            Approver financial = new FinancialManager("黄麒英");
            Approver ceo = new CEO("十三姨");

            //设置职责链
            manager.NextApprover = financial;
            financial.NextApprover = ceo;

            //处理请求
            manager.ProcessRequest(requestDao);
            Console.WriteLine();
            manager.ProcessRequest(requestHuaJi);
            Console.WriteLine();
            manager.ProcessRequest(requestJian);

            Console.ReadLine();
            #endregion
        }
    }
View Code

相关文章: