深入实战责任链模式:在企业级审批流程中的优雅应用

引言:

在复杂的企业系统中,我们经常会遇到这样的场景:一个操作请求需要经过多个环节的处理,每个环节的判断标准不同、处理结果也可能不同。这种需求若用 if-else 编写,不仅冗长且难以维护,后期需求一变更,逻辑维护如履薄冰。

这时候,责任链模式(Chain of Responsibility)就能派上大用场。
本篇文章将通过一个企业审批流程系统
的实际业务场景,带你一步步理解责任链模式的设计思想、核心实现,帮你实现真正可复用、可拓展、可维护的业务逻辑架构。

一、责任链模式简介

责任链模式的定义是:

"使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。"

在 Java 中,它常用来构建一个处理器链,例如日志框架、Servlet Filter、审批流等等。

适用场景:

  • 多个对象可以处理同一请求,具体由运行时决定谁处理。
  • 需要在不明确指定接收者的情况下向多个对象中的一个提交请求。
  • 想要将处理逻辑解耦,提高系统灵活性和可扩展性。

二、业务背景:企业级审批系统需求

我们公司的内部审批系统包含如下审批流程:

  • 员工提交申请。
  • 部门主管审批(审批金额 ≤ 1000)。
  • 总经理审批(1000 < 金额 ≤ 10000)。
  • 财务审批(金额 > 10000)。
  • 特殊情况下(如节假日、超时未审批)还会有自动转审或打回机制。

每个审批节点都可能审批通过 / 拒绝 / 转发

传统实现使用 if-else 实现如下:

java 复制代码
if (amount <= 1000) {
    deptManager.approve(request);
} else if (amount <= 10000) {
    ceo.approve(request);
} else {
    finance.approve(request);
}

这种方式耦合严重、难以扩展,因此我们用责任链模式来优雅实现。

二、责任链模式设计思路图

markdown 复制代码
     ┌─────────────┐
     │ 申请审批请求 │
     └────┬────────┘
          ↓
 ┌─────────────────┐
 │ DepartmentHandler│ → 是否能处理?→ 是→ 处理
 └────┬────────────┘
      ↓ 否
 ┌─────────────────┐
 │     CEOHandler   │ → 是否能处理?→ 是→ 处理
 └────┬────────────┘
      ↓ 否
 ┌─────────────────┐
 │   FinanceHandler │ → 是否能处理?→ 是→ 处理
 └────┬────────────┘
      ↓ 否
 ┌─────────────────┐
 │ DefaultHandler(抛异常/记录)│
 └─────────────────┘

四、代码实现

1. 抽象审批处理器接口

java 复制代码
public abstract class Approver {
    protected Approver next;

    public void setNext(Approver next) {
        this.next = next;
    }

    public abstract void approve(ApprovalRequest request);
}

2. 审批请求

java 复制代码
public class ApprovalRequest {
    private String name;
    private BigDecimal amount;

    public ApprovalRequest(String name, BigDecimal amount) {
        this.name = name;
        this.amount = amount;
    }

    public String getName() { return name; }
    public BigDecimal getAmount() { return amount; }
}

3. 各审批角色处理器实现

部门主管

java 复制代码
public class DeptManagerApprover extends Approver {
    @Override
    public void approve(ApprovalRequest request) {
        if (request.getAmount().compareTo(new BigDecimal("1000")) <= 0) {
            System.out.println("DeptManager approved request of " + request.getName());
        } else if (next != null) {
            next.approve(request);
        }
    }
}

总经理

java 复制代码
public class CEOApprover extends Approver {
    @Override
    public void approve(ApprovalRequest request) {
        if (request.getAmount().compareTo(new BigDecimal("10000")) <= 0) {
            System.out.println("CEO approved request of " + request.getName());
        } else if (next != null) {
            next.approve(request);
        }
    }
}

财务

java 复制代码
public class FinanceApprover extends Approver {
    @Override
    public void approve(ApprovalRequest request) {
        if (request.getAmount().compareTo(new BigDecimal("10000")) > 0) {
            System.out.println("Finance approved request of " + request.getName());
        } else if (next != null) {
            next.approve(request);
        }
    }
}

默认处理器(兜底)

java 复制代码
public class DefaultApprover extends Approver {
    @Override
    public void approve(ApprovalRequest request) {
        System.out.println("No approver found for request: " + request.getName() + ", amount: " + request.getAmount());
    }
}

4 使用实例

java 复制代码
public class ApprovalChainApp {
    public static void main(String[] args) {
        // 构建责任链
        Approver dept = new DeptManagerApprover();
        Approver ceo = new CEOApprover();
        Approver finance = new FinanceApprover();
        Approver defaultHandler = new DefaultApprover();

        dept.setNext(ceo);
        ceo.setNext(finance);
        finance.setNext(defaultHandler);

        // 创建审批请求
        dept.approve(new ApprovalRequest("张三", new BigDecimal("800")));
        dept.approve(new ApprovalRequest("李四", new BigDecimal("5000")));
        dept.approve(new ApprovalRequest("王五", new BigDecimal("20000")));
        dept.approve(new ApprovalRequest("赵六", new BigDecimal("-1"))); // 异常
    }
}

五、优点与企业落地实践总结

✅ 优点:

  • 解耦合:每个处理者只关心自己是否能处理,不关心其他处理者逻辑。
  • 高扩展性:新增一个审批角色,仅需增加一个处理器类并插入链即可。
  • 统一规范:流程清晰,职责单一,便于维护与测试。
  • 自动容错:可在链尾配置默认处理器,处理异常请求或记录日志。

📦 企业实践建议:

  • 将审批链配置在 Spring 容器中,通过注解 + 配置文件来管理顺序。
  • 可结合数据库动态配置审批角色和金额限制,实现动态责任链
  • 可拓展为异步链、事件驱动链,处理异步审批流。

六、结语

责任链模式是一种低调但威力巨大的设计模式。在处理流程型业务(审批、日志、过滤器、消息中间件)时,它为我们提供了一个干净、高内聚的解决方案。

在大型企业系统中,合理使用责任链可以让你在众多开发中脱颖而出,体现系统架构设计的"专业感"。

相关推荐
云边散步6 分钟前
《校园生活平台从 0 到 1 的搭建》第四篇:微信授权登录前端
前端·javascript·后端
架构师沉默9 分钟前
让我们一起用 DDD,构建更美好的软件世界!
java·后端·架构
星眠12 分钟前
学习低代码编辑器第四天
javascript·面试
研究司马懿27 分钟前
【Golang】Go语言函数
开发语言·后端·golang
tuokuac43 分钟前
创建的springboot工程java文件夹下还是文件夹而不是包
java·spring boot·后端
笃行35044 分钟前
搭建专属AI聊天网站:NextChat + 蓝耘MaaS平台完整部署指南
后端
NeverSettle1105741 小时前
手把手教你用nodejs + vue3 实现大文件上传、秒传、断点续传
前端·面试
用户1512905452201 小时前
跨域共享(CORS)&CrossOrigin注解
后端
_風箏1 小时前
Java【代码 16】Milvus向量库工具类和SeetaSDK获取人像向量和属性的工具类分享
后端
用户1512905452201 小时前
C# DateTime日期格式化
后端