首页 > 其他分享 >设计模式(十三)职责链

设计模式(十三)职责链

时间:2023-11-17 10:47:25浏览次数:24  
标签:职责 十三 request name 处理 PurchaseRequest 设计模式 public 请求

一、定义

避免将一个请求的发送者与接受者耦合在一起,让多个对象都有机会接受请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。职责链模式是一种行为型模式

二、描述

职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。包含以下两个角色:
1、Handler(抽象处理者):它定义了一个处理请求的接口,一般设计为抽象类,由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。每一个处理者的下家还是一个处理者,故在抽象处理者中定义了一个抽象处理者类型的对象(如结构图中的successor)作为其对下家的引用,通过该引用,处理者可以连成一条链。
2、ConcreteHandler(具体处理者):它是抽象处理者的子类,可以处理用户请求,在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则则将请求转发给后继者;在具体处理者中可以访问链中的下一个对象,以便请求的转发。

三、例子

X公司承接了某企业SCM(Supply Chain Management,供应链管理)系统的开发任务,其中包含一个采购审批子系统。该企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批:主任可以审批5万元以下(不包括5万)的采购单,副董事长可以审批5万~10万(不包括10万)的采购单,50万元以及以上的采购单就需要开董事会讨论决定。PurchaseRequest:采购请求类

public class PurchaseRequest
{
    // 采购金额
    public double Amount { get; set; }
    // 采购单编号
    public string Number { get; set; }
    // 采购目的
    public string Purpose { get; set; }

    public PurchaseRequest(double amount, string number, string purpose)
    {
        Amount = amount;
        Number = number;
        Purpose = purpose;
    }
}

Approver:审批者类,充当抽象处理者

public abstract class Approver
{
    protected Approver successor; // 定义后继对象
    protected string name;  // 审批者姓名

    public Approver(string name)
    {
        this.name = name;
    }

    // 设置后继者
    public void SetSuccessor(Approver successor)
    {
        this.successor = successor;
    }

    // 抽象请求处理方法
    public abstract void ProcessRequest(PurchaseRequest request);
}

Director、VicePresident、President、Congress:主管、副总裁、总裁、董事会,充当具体处理类

/// <summary>
/// 主管:具体处理类
/// </summary>
public class Director : Approver
{
    public Director(string name) : base(name)
    {
    }

    // 具体请求处理方法
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount < 50000)
        {
            // 处理请求
            Console.WriteLine("主管 {0} 审批采购单:{1},金额:{2} 元,采购目的:{3}。",
                this.name, request.Number, request.Amount, request.Purpose);
        }
        else
        {
            // 如果处理不了,转发请求给更高层领导
            this.successor.ProcessRequest(request);
        }
    }
}

/// <summary>
/// 副总裁:具体处理类
/// </summary>
public class VicePresident : Approver
{
    public VicePresident(string name) : base(name)
    {
    }

    // 具体请求处理方法
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount < 100000)
        {
            // 处理请求
            Console.WriteLine("副总裁 {0} 审批采购单:{1},金额:{2} 元,采购目的:{3}。",
                this.name, request.Number, request.Amount, request.Purpose);
        }
        else
        {
            // 如果处理不了,转发请求给更高层领导
            this.successor.ProcessRequest(request);
        }
    }
}

/// <summary>
/// 总裁:具体处理者
/// </summary>
public class President : Approver
{
    public President(string name) : base(name)
    {
    }

    // 具体请求处理方法
    public override void ProcessRequest(PurchaseRequest request)
    {
        if (request.Amount < 500000)
        {
            // 处理请求
            Console.WriteLine("总裁 {0} 审批采购单:{1},金额:{2} 元,采购目的:{3}。",
                this.name, request.Number, request.Amount, request.Purpose);
        }
        else
        {
            // 如果处理不了,转发请求给更高层领导
            this.successor.ProcessRequest(request);
        }
    }
}

/// <summary>
/// 董事会:具体处理者
/// </summary>
public class Congress : Approver
{
    public Congress(string name) : base(name)
    {
    }

    // 具体请求处理方法
    public override void ProcessRequest(PurchaseRequest request)
    {
        // 处理请求
        Console.WriteLine("董事会 {0} 审批采购单:{1},金额:{2} 元,采购目的:{3}。",
            this.name, request.Number, request.Amount, request.Purpose);
    }
}

Program:客户端测试类

Approver andy = new Director("Andy");
Approver jacky = new VicePresident("Jacky");
Approver ashin = new President("Ashin");
Approver meeting = new Congress("Congress");

andy.SetSuccessor(jacky);
jacky.SetSuccessor(ashin);
ashin.SetSuccessor(meeting);

// 构造采购请求单并发送审批请求
PurchaseRequest request1 = new PurchaseRequest(45000.00, "MANULIFE201706001", "购买PC和显示器");
andy.ProcessRequest(request1);

PurchaseRequest request2 = new PurchaseRequest(60000.00, "MANULIFE201706002", "2017开发团队活动");
andy.ProcessRequest(request2);

PurchaseRequest request3 = new PurchaseRequest(160000.00, "MANULIFE201706003", "2017公司年度旅游");
andy.ProcessRequest(request3);

PurchaseRequest request4 = new PurchaseRequest(800000.00, "MANULIFE201706004", "租用新临时办公楼");
andy.ProcessRequest(request4);

Console.ReadLine();

四、总结

1、优点

(1)使得一个对象无需知道是其他哪一个对象处理其请求,仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链创建,降低了系统的耦合度。
(2)请求处理对象仅需要维持一个指向其后继这的引用,而不需要维持它对所有的候选处理者的引用,可以简化对象之间的相互连接。
(3)在给对象分配职责时,职责链可以带来更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
(4)在系统中增加一个新的具体处理者时无须修改原有系统源代码,只需要在客户端重新建立链式结构即可,从这一点来看是符合开闭原则的。

2、缺点

(1)由于一个请求没有明确的接受者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
(2)对于比较长的职责链,请求的处理可能涉及多个处理对象,系统性能有一定影响且不利于调试。
(3)如果建立链不当,可能会造成循环调用,导致系统进入死循环。

标签:职责,十三,request,name,处理,PurchaseRequest,设计模式,public,请求
From: https://www.cnblogs.com/WinterSir/p/17469116.html

相关文章

  • 第十三章 -------------------WPF应用程序实现单例
    publicpartialclassApp:Application{System.Threading.Mutexmutex;publicApp(){this.Startup+=newStartupEventHandler(App_Startup);}voidApp_Startup(objectsender,StartupEventArgse){boolret;......
  • Java设计模式之组合模式
    在某些情况下,我们需要处理一组对象,这些对象之间具有整体-部分的关系,我们希望能够以一致的方式处理单个对象和对象组合,而不需要对它们进行特殊处理。组合模式的解决方案是将对象组合成树状结构,其中树的节点可以是单个对象或对象组合。这样无论是操作单个对象还是对象组合,都可以使用......
  • 设计模式—结构型模式之外观模式(门面模式)
    设计模式—结构型模式之外观模式(门面模式)外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。例子我们的电脑会有很多组件,比如CPU、硬盘、内存等等;如果我们电脑需要启动的话,需要挨个去调用每个组件的启动方法;停......
  • 面向对象笔记—设计模式
    设计模式一、概念设计模式是一系列在实践中总结出来的可复用的面向对象的软件设计方式设计模式就是描述一个反复出现的问题,以及解决这个问题的方案。可以重复使用这个解决方案而无须再做重复劳动。解决设计问题的固定套路重用,避免代码重复冗余优化体系结构提升系统的可维......
  • 软件设计-职责链模式
    软件设计                 石家庄铁道大学信息学院 实验15:职责链模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解职责链模式的动机,掌握该模式的结构;2、能够利用职责链模式解决实际问题。     [实验任务一]:财务审批......
  • 1.单例设计模式
    单例模式的五种实现方式1、饿汉式(线程安全,调用效率高,但是不能延时加载publicclassImageLoader{privatestaticImageLoaderinstance=newImageLoader;privateImageLoader(){}publicstaticImageLoadergetInstance(){returninstanc......
  • 设计模式-观察者模式
    定义观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。UML结构图如下:其中,Subject类是主题,它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观......
  • 软件设计模式学习每日总结-第四天
    第四天建造者模式:将一个复杂对象的构建和他的表 建造者模式服务于多个成员的产品,无需用户关注建造的细节。 ......
  • 十三:文件操作类&编辑器&上传下载删除读写
    文件获取操作:1functiongetfilename()2{3$dir=getcwd();4$file=scandir($dir);5foreach($fileas$value)6{7if($value!='.'&&$value!='..')8{9$arr[]=$value;1......
  • B站C语言第十三课——操作符
    1,/与%的应用intmain(){ inta=5/2;//商2余1 printf("a=%d\n",a); intb=5%2; printf("b=%d\n",b); return0;}2,移位操作符右移操作符1.算术右移右边丢弃,左边补原符号位2.逻辑右移右边丢弃,左边补0左移操作符左边丢弃,右边补0intmain(){ inta=5; a<<......