重构审批流:用责任链模式实现优雅与高效
在企业级应用开发中,多级审批流程(如请假申请、费用报销、采购订单)是典型且复杂的业务场景。传统的实现方式常陷入if-else或switch-case的泥潭,导致代码臃肿、难以维护、扩展性差。深入实践设计模式之责任链模式优化多级审批流程,其核心价值在于将审批流程中的多个处理节点(如直属领导、部门总监、HR、CEO)解耦为独立的处理对象,并将其串联成一条可灵活编排的链条,使请求能够沿链传递,直至被处理。这显著提升了流程的灵活性、可维护性和可测试性,是应对业务规则频繁变动的架构利器。
一、 痛点剖析:传统审批流程的代码“坏味道”

在探讨解决方案前,让我们先看一段典型的、亟待优化的审批代码:
public String handleApproval(ApprovalRequest request) {
if (request.getType().equals(“LEAVE”)) { // 请假审批
if (request.getDays() <= 3) {
// 直属领导审批逻辑
boolean result = directLeaderApprove(request);
if (!result) return “直属领导驳回”;
} else if (request.getDays() <= 10) {
// 直属领导审批
if (!directLeaderApprove(request)) return “直属领导驳回”;
// 部门总监审批
if (!departmentHeadApprove(request)) return “部门总监驳回”;
} else {
// 直属领导审批
if (!directLeaderApprove(request)) return “直属领导驳回”;
// 部门总监审批
if (!departmentHeadApprove(request)) return “部门总监驳回”;
// HR审批
if (!hrApprove(request)) return “HR驳回”;
}
} else if (request.getType().equals(“EXPENSE”)) { // 费用报销
// 另一套复杂的if-else嵌套...
}
return “审批通过”;
}
这段代码的“坏味道”非常浓烈:1. 违反开闭原则:新增或调整一个审批节点(如增加CFO审批),必须修改这个庞大的方法,风险极高。
2. 代码臃肿,可读性差:多重嵌套的if-else逻辑使核心业务意图被淹没。
3. 难以复用和测试:每个审批逻辑紧密耦合,无法独立单元测试。
这正是设计模式之责任链模式优化多级审批流程所要解决的典型问题。在鳄鱼java的代码重构案例中,此类场景极为常见。
二、 责任链模式:化繁为简的设计哲学
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式。其核心思想是:让多个处理器(Handler)都有机会处理同一个请求,将这些处理器连成一条链,并沿着这条链传递请求,直到有一个处理器处理它为止。
模式的三个核心角色: 1. 抽象处理器(Handler):定义处理请求的接口,通常包含一个处理方法和一个设置后继者的方法。 2. 具体处理器(Concrete Handler):实现抽象处理器接口,处理其负责的请求。如果可以处理,则处理;否则,将请求转发给后继者。 3. 客户端(Client):组装责任链,并将请求发送到链上的第一个处理器。
将这一模式映射到审批流程:每个审批人(直属领导、总监等)就是一个具体处理器,他们共同实现一个审批处理器接口。客户端根据审批规则将这些处理器链接起来,形成一个审批链。申请单(请求)从链首开始流动,被第一个有权限的审批人处理或传递下去。
三、 实战:构建可配置的请假审批链
让我们用代码具体实现一个请假审批流程。假设规则为:≤3天直属领导批,≤10天需直属领导和部门总监批,>10天需直属领导、部门总监和HR批。
1. 定义抽象审批处理器与请求对象
// 审批请求对象 @Data public class LeaveRequest { private String employeeId; private String employeeName; private int leaveDays; private String reason; // 其他字段... }
// 抽象处理器:定义审批行为 public abstract class ApprovalHandler { protected ApprovalHandler nextHandler; // 持有下一个处理器的引用 // 设置后继者 public void setNextHandler(ApprovalHandler nextHandler) { this.nextHandler = nextHandler; } // 抽象审批方法 public abstract void handle(LeaveRequest request); }
2. 实现具体审批处理器
每个处理器只关心自己职责范围内的审批逻辑,职责单一且清晰。// 直属领导审批处理器 @Component public class DirectLeaderHandler extends ApprovalHandler { @Override public void handle(LeaveRequest request) { if (request.getLeaveDays() <= 3) { // 模拟审批逻辑 System.out.println(“直属领导审批通过:【” + request.getEmployeeName() + “】的” + request.getLeaveDays() + “天请假申请”); // 处理完成,责任链终止(可根据业务决定是否继续传递,如记录日志) return; } else { System.out.println(“直属领导无权限,转交下一级”); // 无权处理,传递给下一个处理器 if (nextHandler != null) { nextHandler.handle(request); } else { System.out.println(“审批链结束,无人处理该请求!”); } } } }// 部门总监审批处理器 @Component public class DepartmentHeadHandler extends ApprovalHandler { @Override public void handle(LeaveRequest request) { if (request.getLeaveDays() <= 10) { System.out.println(“部门总监审批通过:【” + request.getEmployeeName() + “】的” + request.getLeaveDays() + “天请假申请”); return; } else { System.out.println(“部门总监无权限,转交下一级”); if (nextHandler != null) { nextHandler.handle(request); } } } }
// HR审批处理器 @Component public class HrHandler extends ApprovalHandler { @Override public void handle(LeaveRequest request) { if (request.getLeaveDays() > 10) { System.out.println(“HR审批通过:【” + request.getEmployeeName() + “】的” + request.getLeaveDays() + “天请假申请”); return; } // 如果不是>10天,理论上不应流转到HR,这里作为兜底 if (nextHandler != null) { nextHandler.handle(request); } } }
3. 组装责任链(客户端) 在Spring环境中,我们可以通过配置类灵活地组装链条:
@Configuration
public class ApprovalChainConfig {
@Bean
public ApprovalHandler approvalChain(DirectLeaderHandler directLeader,
DepartmentHeadHandler departmentHead,
HrHandler hr) {
// 构建责任链:直属领导 -> 部门总监 -> HR
directLeader.setNextHandler(departmentHead);
departmentHead.setNextHandler(hr);
// 返回链头
return directLeader;
}
}
4. 业务服务调用
当调用@Service public class LeaveService { @Autowired private ApprovalHandler approvalChain; // 注入组装好的链public void submitLeaveApplication(LeaveRequest request) { System.out.println(“开始处理请假申请...”); // 将请求投入责任链 approvalChain.handle(request); System.out.println(“请假申请处理流程结束。”); }
}
submitLeaveApplication时,请求会从直属领导开始,根据条件自动流转。这就是一个清晰、完整的设计模式之责任链模式优化多级审批流程的实现。
四、 进阶优化:动态链、中断与回溯
基础实现后,我们可以根据复杂业务需求进行增强。
1. 动态构建责任链 审批规则可能来自数据库配置。我们可以实现一个`HandlerFactory`,根据请求类型和规则动态创建和组装处理器链,实现真正的可配置化审批流。
2. 显式中断与状态传递 有时需要某一级审批驳回后立即终止流程。我们可以修改`handle`方法的返回值或通过请求上下文传递状态。
public enum ApprovalResult {
PASS, REJECT, PENDING, FORWARD
}
public abstract class ApprovalHandler {
public abstract ApprovalResult handle(LeaveRequest request);
}
// 在具体处理器中
public ApprovalResult handle(LeaveRequest request) {
if (canHandle(request)) {
boolean approve = doApprove(request); // 实际审批操作
return approve ? ApprovalResult.PASS : ApprovalResult.REJECT; // 驳回则终止
}
return ApprovalResult.FORWARD; // 需要转发
}
// 客户端调用链时,根据返回值决定是否继续
3. 与策略模式结合 对于不同审批人可能有不同的审批策略(如严格模式、宽松模式),可以在具体处理器内部使用策略模式,进一步解耦审批逻辑。在鳄鱼java的复杂流程引擎中,这种组合模式被广泛应用。
五、 总结:从模式应用到架构思维
实践设计模式之责任链模式优化多级审批流程,其收获远不止于实现一个功能。它训练我们以“分治”和“组装”的思维来设计系统。每个处理器成为一个独立的、可测试的单元,链的组装过程变为一种声明式或配置式的行为,这为流程的可视化管理、A/B测试和动态调整打下了坚实基础。
在鳄鱼java的项目中,责任链模式不仅用于审批流,还成功应用于日志过滤链、权限检查链、风控规则链、数据清洗管道等场景。它让系统在面对变化时更加从容。
现在,请审视你正在维护的系统:是否存在那种长达数百行、嵌套无数层的流程处理方法?下一次当你需要添加一个新的处理步骤或调整顺序时,是否会感到恐惧?尝试用责任链的模式思维对其进行分析和重构。你会发现,代码的清晰度和你对业务的掌控力,都将获得质的提升。记住,优秀的架构不是一次性设计出来的,而是通过持续应用这些经过验证的模式,一步步演化出来的。
版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。





