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

引言:

在复杂的企业系统中,我们经常会遇到这样的场景:一个操作请求需要经过多个环节的处理,每个环节的判断标准不同、处理结果也可能不同。这种需求若用 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 容器中,通过注解 + 配置文件来管理顺序。
  • 可结合数据库动态配置审批角色和金额限制,实现动态责任链
  • 可拓展为异步链、事件驱动链,处理异步审批流。

六、结语

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

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

相关推荐
东阳马生架构2 小时前
生成订单链路中的技术问题说明文档
后端
程序员码歌5 小时前
【零代码AI编程实战】AI灯塔导航-总结篇
android·前端·后端
java坤坤6 小时前
GoLand 项目从 0 到 1:第八天 ——GORM 命名策略陷阱与 Go 项目启动慢问题攻坚
开发语言·后端·golang
元清加油6 小时前
【Golang】:函数和包
服务器·开发语言·网络·后端·网络协议·golang
bobz9656 小时前
GPT-4.1 对比 GPT-4o
后端
Java小白程序员7 小时前
Spring Framework :IoC 容器的原理与实践
java·后端·spring
小小愿望7 小时前
前端无法获取响应头(如 Content-Disposition)的原因与解决方案
前端·后端
追逐时光者8 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 50 期(2025年8.11-8.17)
后端·.net
杨DaB8 小时前
【SpringBoot】Swagger 接口工具
java·spring boot·后端·restful·swagger
恋喵大鲤鱼9 小时前
Golang 后台技术面试套题 1
面试·golang