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

设计模式——职责链模式

设计模式——职责链模式

参考尚硅谷宋红康老师的图解设计模式

场景描述

学校采购一批 OA 系统时,需要根据采购金额决定审批人:

例如:

  • 5000 元,主任审批

  • 6000 元,校长审批

  • 8000 元,教育部审批

传统解决方案

传统方案中,采购金额与审批人之间存在硬编码关系,通常使用 if-elseswitch 来判断金额,并决定审批人。
这种方式有以下问题:

  • 代码不灵活:如果金额范围改变,客户端需要进行大规模修改。
  • 强耦合:客户端需要了解所有审批级别和金额区间,导致系统的代码维护困难。

职责链模式通过将请求的处理责任沿着一个链条传递来解决上述问题。每个处理者持有对下一个处理者的引用,如果当前处理者无法处理请求,则将请求传递给下一个处理者,直到有处理者能够处理请求。
在这里插入图片描述

职责链模式的组成部分
  1. Handler(处理者):定义一个处理请求的接口,并持有对下一个处理者的引用。
  2. ConcreteHandler(具体处理者):实现了具体的请求处理逻辑,如果该处理者无法处理请求,则将请求传递给下一个处理者。
  3. Request(请求):表示一个具体的请求,通常包含多个属性,如请求的金额、类型等。
示例图

image-20250214195006750

职责链模式

具体实现
Approver(抽象处理者)
package top.miqiu.designPatternDemo.responsibilityChan;

import lombok.Data;

@Data
public abstract class Approver {
    Approver approver;  // 下一个处理者
    String name;

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

    // 处理审批请求的抽象方法,具体实现由子类完成
    public abstract void processRequest(Purchaserequest purchaserequest);
}
Client(客户端)
package top.miqiu.designPatternDemo.responsibilityChan;

import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.CollegeAprover;
import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.DepartmentApprover;
import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.SchoolMasterApprover;
import top.miqiu.designPatternDemo.responsibilityChan.processerImpl.ViceSchoolMasterApprover;

public class Client {
    public static void main(String[] args) {
        // 创建采购请求
        Purchaserequest purchaserequest = new Purchaserequest(1, 1000, 1);

        // 创建相关的审批人
        DepartmentApprover departmentApprover = new DepartmentApprover("张主任");
        CollegeAprover collegeAprover = new CollegeAprover("李院长");
        ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校长");
        SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("杨校长");

        // 构建审批链:从部门审批到校长审批
        departmentApprover.setApprover(collegeAprover);
        collegeAprover.setApprover(viceSchoolMasterApprover);
        viceSchoolMasterApprover.setApprover(schoolMasterApprover);

        // 发起请求并处理
        schoolMasterApprover.processRequest(purchaserequest);
    }
}
Purchaserequest(请求类)
package top.miqiu.designPatternDemo.responsibilityChan;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Purchaserequest {
    private int type = 0;  // 请求类型
    private float price = 0.0f;  // 请求金额
    private int id = 0;  // 请求ID
}
SchoolMasterApprover(具体处理者)
package top.miqiu.designPatternDemo.responsibilityChan.processerImpl;

import top.miqiu.designPatternDemo.responsibilityChan.Approver;
import top.miqiu.designPatternDemo.responsibilityChan.Purchaserequest;

public class SchoolMasterApprover extends Approver {

    public SchoolMasterApprover(String name) {
        super(name);
    }

    @Override
    public void processRequest(Purchaserequest purchaserequest) {
        // 校长审批金额大于 7000 的请求
        if (purchaserequest.getPrice() > 7000) {
            System.out.println("请求ID:" + purchaserequest.getId() + " 由 " + this.getName() + " 处理");
        } else {
            // 转交给下一个处理者
            this.getApprover().processRequest(purchaserequest);
        }
    }
}

在源码中的运用

在 Spring MVC 中,请求的处理遵循类似的职责链模式。具体而言,HandlerExecutionChain 的职责是将请求分配给链路上的处理器。Spring MVC 中有一个拦截器链,负责请求的预处理和后处理。

HandlerExecutionChain 内部维护了一个 HandlerExecutionInterceptor 的集合,拦截器会在请求处理前后分别执行 preHandlepostHandle 方法,从而形成职责链的模式。每个拦截器执行时,都可以判断是否继续处理请求,或者终止链的执行。

注意事项与细节

好处:
  • 解耦请求和处理逻辑:请求和处理过程解耦,使得对象不需要知道链的结构,便于扩展和维护。
  • 灵活性:可以通过动态添加处理者来灵活调整审批流程。
缺点:
  • 性能开销:如果链条过长,可能会对性能产生一定影响,需要考虑最大节点数的控制。
  • 调试困难:链式结构的调试较为复杂,可能需要追踪多个处理者的执行流程。

总结

职责链模式非常适合用于多个对象可以处理同一请求的场景。它使得系统可以灵活地调整请求的处理顺序和流程,而不需要修改客户端代码,从而降低了系统的耦合度和维护成本。

相关文章:

  • Maven 中的 `<dependencyManagement>` 标签及其高级用法
  • centos7安装vscode
  • MySql从入门到精通
  • qt 控件的焦点事件
  • 共享设备管理难?MDM助力Kiosk模式一键部署
  • P2704 [NOI2001] 炮兵阵地
  • 血压高吃哪些水果比较好喵?
  • VM ubuntu20.04 虚拟机与主机之间不能互相复制的解决
  • Deepseek R1模型本地化部署+API接口调用详细教程:释放AI生产力
  • 云原生时代的后端开发:架构、工具与最佳实践
  • 6 Flink Table 和相关概念
  • TCP可靠传输的ARQ协议
  • 20250214在ubuntu20.04下使用obs studio录制外挂的1080p的USB摄像头【下载安装】
  • vm vitualbox和主机ssh连接,使用net 和仅主机网卡连接
  • Python爬虫抓取数据时,如何设置请求头?
  • 【人工智能】python如何提供API接口供他人调用
  • EDR和杀软的区别
  • C++ Primer 参数传递
  • PyCharm控制台中文乱码
  • DeepSeek与核货宝订货系统的协同进化:智能商业范式重构
  • 第十二届警博会在京开幕:12个国家和地区835家企业参展
  • 寒武纪陈天石:公司的产品力获得了行业客户广泛认可,市场有望迎来新增量需求
  • 全国层面首次!《防震减灾基本知识与技能大纲》发布
  • 北美票房|昔日偶像风光不再,乔什·哈内特新片开画不佳
  • 尹锡悦涉嫌发动内乱案举行第三次庭审
  • 习近平将出席中国—拉美和加勒比国家共同体论坛第四届部长级会议开幕式并发表重要讲话