(46)C#设计模式—— 责任链模式

引言

在现实生活中,有很多请求并不是一个人说了算,例如面试时的工资,地狱1万的可能技术经理就可以决定了,但是1万到1万5的公司可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所以面试的话,经常会有面试者说,你这个薪水我觉得你这技术可以拿这个薪水的,但是还需要技术总监的批准等话。这个例子引出了我们要介绍的责任链模式。

定义

从生活中的例子可以看出,某个请求需要几个人的审批,即使技术经理审批完了,还需要上一级的审批。这样的例子,还有公司的请假,根据不同时长的请假要求,可能需要不同的人来审核。

责任链模式指的是某个请求需要多个对象处理,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链子,并沿着这条链子传递请求,知道有对象处理它为止。

角色

责任链模式涉及到的角色有:

  • 抽象处理角色:定义一个处理请求的接口,这个接口通常由接口或者抽象类来实现。
  • 具体处理者角色:具体处理者接收到请求后,可以选择将该请求处理掉,或者将请求传递给下一个处理者。因此,每个具体处理者需要保存下一个处理者的引用,方便把请求传递下去。

实现

以公司采购东西的例子来说明如何实现责任链模式。公司规定,采购价格总价在1万之内,经理级别的人批准即可。总价大于1万小于2万5的则还需要副总进行批准,总价大于2万5小于10万的还需要总经理的批准,而总价大于10万的则需要组织会议进行讨论。对于这样的一个需求,最直观的方法就是设计一个方法,参数是采购的总价,然后在这个方法内对价格进行调整判断,然后针对不同的条件交给不同级别的人去处理,这样确实可以解决问题。但是这样设计,我们就需要使用多重if-else语句来进行判断,当加入一个新的条件范围时,我们不得不去修改原来设计的方法,不易于扩展。利用责任链模式可以解决这样的问题。

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

namespace _37ZeRenLianPatternDemo
{
    //采购请求
    public class PurchaseRequest
    {
        //金额
        public double Amount { get; set; }
        //产品名字
        public string ProductName { get; set; }
        public PurchaseRequest(double amount, string productName)
        {
            Amount = amount;
            ProductName = productName;
        }
    }
    //审批人
    public abstract class Approver
    {
        public Approver NextApprover { get; set; }
        public string Name { get; set; }
        public Approver(string name)
        {
            this.Name = name;
        }
        public abstract void ProcessRequest(PurchaseRequest request);
    }
    //具体审批者
    public class Manager : Approver
    {
        public Manager(string name) : base(name)
        {
        }
        public override void ProcessRequest(PurchaseRequest request)
        {
            if(request.Amount<10000.0)
            {
                Console.WriteLine("{0}-{1} approved the request of purshing{2}", this, Name, request.ProductName);
            }
            else
            {
                NextApprover.ProcessRequest(request);
            }
        }
    }
    public class VicePresident : Approver
    {
        public VicePresident(string name) : base(name)
        {
        }

        public override void ProcessRequest(PurchaseRequest request)
        {
            if (request.Amount < 25000.00)
            {
                Console.WriteLine("{0}-{1} approved the request of purshing{2}", this, Name, request.ProductName);
            }
            else if (NextApprover != null)
            {
                NextApprover.ProcessRequest(request);
            }
        }
    }
    public class President : Approver
    {
        public President(string name) : base(name)
        {
        }

        public override void ProcessRequest(PurchaseRequest request)
        {
            if (request.Amount < 100000.00)
            {
                Console.WriteLine("{0}-{1} approved the request of purshing{2}", this, Name, request.ProductName);
            }
            else
            {
                Console.WriteLine("Request需要组织会议");
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            PurchaseRequest requestPhone = new PurchaseRequest(4000.00, "Phone");
            PurchaseRequest requestComputer = new PurchaseRequest(10000.00, "Computer");
            PurchaseRequest requestAircontiditon = new PurchaseRequest(40000.0, "Aircondition");
            PurchaseRequest request = new PurchaseRequest(200000.00, "Car");

            Approver manager = new Manager("Tom");
            Approver VicePresident = new VicePresident("Bob");
            Approver President = new President("James");

            //设置责任链
            manager.NextApprover = VicePresident;
            VicePresident.NextApprover = President;
            //处理请求
            manager.ProcessRequest(requestPhone);
            manager.ProcessRequest(requestComputer);
            manager.ProcessRequest(requestAircontiditon);
            manager.ProcessRequest(request);

        }
    }
}

使用场景

  • 一个系统的审批需要多个对象才能完成处理的情况下,例如请假系统等。
  • 码中存在多个if-else语句的情况下,此时可以考虑使用责任链模式来对代码进行重构。

优缺点

优点

  • 降低了请求的发送者和接收者之间的耦合
  • 把多个条件判定分散到各个处理类中,使得代码更清晰,责任更明确

缺点

  • 在找到正确的处理对象之前,所有的条件判定都要执行一遍,当责任链过长时,可能会引起性能的问题
  • 可能导致某个请求不被处理

总结

责任链降低了请求端和接收端之间的耦合,使多个对象都有机会处理某个请求。 如考试中作弊传纸条,拍拖传情书一般。可能直接传到目的地,也可能中间经过多次传递

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章