当前位置: 首页 > article >正文

责任链模式(ChainofResponsibilityPattern)

文章目录

  • 1.定义
  • 2.结构
  • 3.问题描述
  • 代码实现

1.定义

允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
在这里插入图片描述

2.结构

在这里插入图片描述

  • 处理者(Handler):声明了所有具体处理者的通用接口。 该接口通常仅包含单个方法用于请求处理, 但有时其还会包含一个设置链上下个处理者的方法。
  • 基础处理者(Base Handler):是一个可选的类, 你可以将所有处理者共用的样本代码放置在其中。
    通常情况下, 该类中定义了一个保存对于下个处理者引用的成员变量。 客户端可通过将处理者传递给上个处理者的构造函数或设定方法来创建链。 该类还可以实现默认的处理行为: 确定下个处理者存在后再将请求传递给它。
  • 具体处理者(Concrete Handlers) :包含处理请求的实际代码。 每个处理者接收到请求后, 都必须决定是否进行处理, 以及是否沿着链传递请求。
    处理者通常是独立且不可变的, 需要通过构造函数一次性地获得所有必要地数据。
  • 客户端 (Client):可根据程序逻辑一次性或者动态地生成链。 值得注意的是, 请求可发送给链上的任意一个处理者, 而非必须是第一个处理者。

3.问题描述

    以公司采购东西为例子来实现责任链模式。公司规定:

  • 采购总价 < 10000.0,处理人:经理(Manager)
  • 10000.0 < 采购总价 < 25000.0,处理人:副总(VicePresident)
  • 25000.0 < 采购总价 < 100000.0,处理人:总经理(President)

    对于这样一个需求,最直观的方法就是设计一个方法,参数是采购的总价,然后在这个方法内对价格进行调整判断,然后针对不同的条件交给不同级别的人去处理,这样确实可以解决问题,但这样一来,我们就需要多重if-else语句来进行判断,但当加入一个新的条件范围时,我们又不得不去修改原来设计的方法来再添加一个条件判断,这样的设计显然违背了“开-闭”原则。这时候,可以采用责任链模式来解决这样的问题。

代码实现

采购请求:

// 采购请求
public class PurchaseRequest
{
    public double Amount; // 金额
    public string? ProductName{get; set;} // 产品名

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

审批人(抽象类):

// 审批人,handler
public abstract class Approver
{
    public string? Name{get; set;}

    private Approver? _nextApprover;

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

    // 设置下一个审批人
    public Approver SteNextApprover(Approver approver)
    {
        _nextApprover = approver;
        return approver;
    }

    // 审批
    public virtual void Handle(PurchaseRequest request)
    {
        if (_nextApprover != null)
            _nextApprover.Handle(request);
        else
            Console.WriteLine("事件链无法处理该请求");
    }
}

具体审批人:

// 经理
public class Manager : Approver
{
    public Manager(string name) : base(name){}

    public override void Handle(PurchaseRequest request)
    {
        if (request.Amount < 10000.0)
            Console.WriteLine($"Manager({Name})处理了请求采购请求({request.ProductName}, {request.Amount})");
        else
            base.Handle(request);
    }
}

// 副总
public class VicePresident : Approver
{
    public VicePresident(string name) : base(name){}

    public override void Handle(PurchaseRequest request)
    {
        if (request.Amount < 25000.0)
            Console.WriteLine($"VicePresident({Name})处理了请求采购请求({request.ProductName}, {request.Amount})");
        else
            base.Handle(request);
    }
}

// 总经理
public class President : Approver
{
    public President(string name) : base(name){}

    public override void Handle(PurchaseRequest request)
    {
        if (request.Amount < 100000.0)
            Console.WriteLine($"President({Name})处理了请求采购请求({request.ProductName}, {request.Amount})");
        else
            base.Handle(request);
    }
}

客户端:

Console.WriteLine("----------------------- 责任链模式 ----------------------------");
PurchaseRequest requestTelphone = new PurchaseRequest("Telphone", 4000.0);
PurchaseRequest requestSoftware = new PurchaseRequest("Visual Studio", 10000.0);
PurchaseRequest requestComputers = new PurchaseRequest("Computers", 40000.0);

Approver manager = new Manager("LearningHard");
Approver Vp = new VicePresident("Tony");
Approver Pre = new President("BossTom");

// 设置责任链
manager.SteNextApprover(Vp).SteNextApprover(Pre);

// 处理请求
manager.Handle(requestTelphone);
manager.Handle(requestSoftware);
manager.Handle(requestComputers);

Vp.Handle(requestSoftware);

Manager(LearningHard)处理了请求采购请求(Telphone, 4000)
VicePresident(Tony)处理了请求采购请求(Visual Studio, 10000)
President(BossTom)处理了请求采购请求(Computers, 40000)
VicePresident(Tony)处理了请求采购请求(Visual Studio, 10000)


http://www.kler.cn/a/449439.html

相关文章:

  • 本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——13使用Resnet-Bin
  • C/C++基础错题归纳
  • 用Python PySide6 复刻了两软件UI 做下练习
  • python使用pip进行库的下载
  • 5G -- 5G网络架构
  • ChatGPT接口测试用例生成的流程
  • 软件测试工程师撰写优质测试用例的秘籍
  • Linux 环境搭建(云服务器和XShell)
  • C# Random 随机数 全面解析
  • SpringBoot——核心概念
  • 【国产NI替代】基于全国产FPGA的16振动+2转速+8路IO口输入输出(24bits)256k采样率,高精度终端采集板卡
  • 再服务器上建立新的编译环境
  • ubuntu18.04升级到ubuntu20.04
  • WPF+MVVM案例实战与特效(四十六)- 打造动态背景时钟控件,轻松提升界面美感
  • Android 代码模式的理解
  • Flamingo:少样本多模态大模型
  • 目标检测-R-CNN
  • Pytorch | 利用EMI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
  • 【阅读记录-章节6】Build a Large Language Model (From Scratch)
  • c# 不同数据类型转换
  • uniapp-微信小程序调用摄像头
  • springboot474基于web的垃圾分类回收系统(论文+源码)_kaic
  • 低代码开源项目Joget的研究——安装部署
  • 动态规划<四> 回文串问题(含对应LeetcodeOJ题)
  • stm32实现回调功能
  • jsp-servlet开发