2025/10/9日 每日总结 设计模式实践:职责链模式之财务分级审批系统案例解析
设计模式实践:职责链模式之财务分级审批系统案例解析
在日常业务中,很多场景需要按照预设规则逐级处理请求(如审批、投诉处理等)。职责链模式通过构建“请求处理链”,让请求在链上自动传递,直到找到能处理它的对象,从而实现请求发送者与处理者的解耦。本文将通过财务分级审批的实际场景,详细拆解职责链模式的实现逻辑与应用价值。
一、实验背景与需求
本次实践的核心需求是设计物资采购分级审批系统,具体规则如下:
-
主任:审批1万元及以下的采购单
-
部门经理:审批5万元及以下的采购单
-
副总经理:审批10万元及以下的采购单
-
总经理:审批20万元及以下的采购单
-
20万元以上:需召开职工大会讨论决定
-
要求:请求自动逐级传递,无需发送者关注具体处理者
二、职责链模式核心结构
职责链模式的关键在于抽象处理者类定义处理接口和后继者引用,具体处理者类实现自身处理逻辑,无法处理时将请求传递给后继者。本次案例的结构设计如下:
1. 核心组件划分
| 组件类型 | 具体实现 | 职责描述 |
|---|---|---|
| 抽象处理者 | Leader | 定义审批者的核心接口,维护后继者引用,提供设置后继者的方法 |
| 具体处理者 | Director(主任)、DepartmentManager(部门经理)、GeneralManager(副总经理)、VicManager(总经理) | 实现各自审批权限的处理逻辑,超出权限则传递给后继者 |
| 请求类 | Request | 封装采购请求信息(采购金额) |
2. 类图结构
┌─────────────────┐
│ Request │ ← 请求类(封装采购信息)
├─────────────────┤
│ - cost: BigDecimal │ ← 采购金额
├─────────────────┤
│ + Request(cost: BigDecimal) │
│ + getCost(): BigDecimal │
└─────────────────┘
┌─────────────────┐
│ Leader │ ← 抽象处理者(审批者)
├─────────────────┤
│ - name: String │ ← 审批者姓名
│ - successor: Leader │ ← 后继审批者(职责链下一环)
├─────────────────┤
│ + Leader(name: String) │
│ + setSuccessor(successor: Leader): void │ ← 设置后继者
│ + abstract handleRequest(request: Request): void │ ← 处理请求(抽象方法)
└─────────────────┘
▲
│
┌───────────────┬───────────────┬───────────────┬───────────────┐
│ Director │DepartmentManager│GeneralManager│ VicManager │ ← 具体处理者
├───────────────┤───────────────┤───────────────┤───────────────┤
│ + handleRequest() │ + handleRequest() │ + handleRequest() │ + handleRequest() │
│ (≤1万) │ (≤5万) │ (≤10万) │ (≤20万) │
└───────────────┘───────────────┘───────────────┘───────────────┘
↓
职工大会(最终处理)
三、完整实现代码(Java)
1. 请求类:Request.java
import java.math.BigDecimal;
// 采购请求类:封装采购金额信息
class Request {
private BigDecimal cost;
// 构造函数:初始化采购金额
public Request(BigDecimal cost) {
this.cost = cost;
}
// 获取采购金额
public BigDecimal getCost() {
return cost;
}
// 设置采购金额(可选)
public void setCost(BigDecimal cost) {
this.cost = cost;
}
}
2. 抽象处理者:Leader.java
import java.math.BigDecimal;
// 抽象领导者类:职责链的抽象处理者
abstract class Leader {
protected String name;
protected Leader successor; // 后继审批者(下一级领导)
// 构造函数:初始化审批者姓名
public Leader(String name) {
this.name = name;
}
// 设置后继审批者
public void setSuccessor(Leader successor) {
this.successor = successor;
}
// 处理采购请求的抽象方法(子类必须实现)
public abstract void handleRequest(Request request);
}
3. 具体处理者类
主任类(≤1万):Director.java
import java.math.BigDecimal;
class Director extends Leader {
public Director(String name) {
super(name);
}
@Override
public void handleRequest(Request request) {
BigDecimal limit = new BigDecimal("10000.00");
// 金额在主任审批范围内,直接处理
if (request.getCost().compareTo(limit) <= 0) {
System.out.println("主任 " + name + " 审批,采购金额为:" + request.getCost());
} else {
// 超出权限,传递给后继者(部门经理)
if (successor != null) {
this.successor.handleRequest(request);
}
}
}
}
部门经理类(≤5万):DepartmentManager.java
import java.math.BigDecimal;
class DepartmentManager extends Leader {
public DepartmentManager(String name) {
super(name);
}
@Override
public void handleRequest(Request request) {
BigDecimal limit = new BigDecimal("50000.00");
if (request.getCost().compareTo(limit) <= 0) {
System.out.println("部门经理 " + name + " 审批,采购金额为:" + request.getCost());
} else {
if (successor != null) {
this.successor.handleRequest(request);
}
}
}
}
副总经理类(≤10万):GeneralManager.java
import java.math.BigDecimal;
class GeneralManager extends Leader {
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(Request request) {
BigDecimal limit = new BigDecimal("100000.00");
if (request.getCost().compareTo(limit) <= 0) {
System.out.println("副总经理 " + name + " 审批,采购金额为:" + request.getCost());
} else {
if (successor != null) {
this.successor.handleRequest(request);
}
}
}
}
总经理类(≤20万):VicManager.java
import java.math.BigDecimal;
class VicManager extends Leader {
public VicManager(String name) {
super(name);
}
@Override
public void handleRequest(Request request) {
BigDecimal limit = new BigDecimal("200000.00");
if (request.getCost().compareTo(limit) <= 0) {
System.out.println("总经理 " + name + " 审批,采购金额为:" + request.getCost());
} else {
// 超出所有领导权限,需开职工大会
System.out.println("采购金额为:" + request.getCost() + " 数额过大,需开会决定!");
}
}
}
4. 测试类:ChainOfResponsibilityTest.java
import java.math.BigDecimal;
public class ChainOfResponsibilityTest {
public static void main(String[] args) {
// 1. 创建各级审批者
Leader director = new Director("Tom"); // 主任
Leader deptManager = new DepartmentManager("Jack"); // 部门经理
Leader generalManager = new GeneralManager("Rose"); // 副总经理
Leader vicManager = new VicManager("Wang"); // 总经理
// 2. 构建职责链:主任 → 部门经理 → 副总经理 → 总经理
director.setSuccessor(deptManager);
deptManager.setSuccessor(generalManager);
generalManager.setSuccessor(vicManager);
// 3. 创建测试采购请求
Request request1 = new Request(new BigDecimal("70000.00")); // 7万(副总经理审批)
Request request2 = new Request(new BigDecimal("150000.00")); // 15万(总经理审批)
Request request3 = new Request(new BigDecimal("210000.00")); // 21万(需开会)
// 4. 提交审批(仅需提交给链首,自动传递)
System.out.println("=== 采购审批测试 ===");
director.handleRequest(request1);
director.handleRequest(request2);
director.handleRequest(request3);
}
}
四、运行结果
=== 采购审批测试 ===
副总经理 Rose 审批,采购金额为:70000.00
总经理 Wang 审批,采购金额为:150000.00
采购金额为:210000.00 数额过大,需开会决定!
从运行结果可以看出:
-
7万采购请求经主任、部门经理传递到副总经理,由副总经理审批
-
15万采购请求传递到总经理,由总经理审批
-
21万采购请求超出所有领导权限,提示需开会决定
-
客户端仅需将请求提交给链首(主任),无需关注中间传递过程
五、职责链模式核心优势与特性
1. 核心优势
-
解耦请求发送与处理:发送者无需知道具体处理者,处理者也无需知道请求来源,仅需关注自身职责
-
灵活性高:可动态调整职责链的结构(新增/删除处理者、调整顺序),符合开闭原则
-
简化代码:避免大量嵌套的条件判断(如
if-else判断金额区间),代码更清晰易维护 -
责任明确:每个处理者仅处理自身权限范围内的请求,职责单一
2. 注意事项
-
避免请求丢失:需确保职责链覆盖所有场景(如本案例中20万以上的特殊处理)
-
避免循环依赖:职责链不可形成闭环,否则会导致请求无限循环传递
-
性能考虑:职责链过长可能导致请求传递耗时,需合理设计链的长度
六、适用场景总结
职责链模式特别适合以下场景:
-
存在多级处理流程,请求需逐级传递(如审批系统、投诉处理、日志记录)
-
希望解耦请求发送者与处理者,无需硬编码处理者引用
-
需动态调整处理流程或处理规则
-
避免大量嵌套条件判断的场景
通过本次财务分级审批系统的实践案例,深刻体会到职责链模式在流程化业务中的优势。它将复杂的多级处理逻辑拆分为独立的处理者,通过链条串联实现请求自动传递,既简化了代码结构,又提高了系统的灵活性和可维护性。在实际开发中,当遇到类似的分级处理场景时,职责链模式无疑是一个理想的解决方案。

浙公网安备 33010602011771号