摘要
责任链设计模式是一种行为型设计模式,旨在将请求的发送者与接收者解耦,通过多个处理器对象按链式结构依次处理请求,直到某个处理器处理为止。它包含抽象处理者、具体处理者和客户端等核心角色。该模式适用于多个对象可能处理请求的场景,如风控系统中的贷款申请流程,通过链式组合处理整个流程。实现方式包括链式引用和集合遍历等,适用于信贷申请风控校验等实际应用。
1. 责任链设计模式定义
责任链设计模式(Chain of Responsibility Pattern)是一种行为型设计模式,允许多个处理器对象都有机会处理请求,避免请求的发送者与接收者之间的耦合关系。这些处理器按照链式结构连接,每个处理器决定是否处理请求,或将其传递给链上的下一个处理器。
1.1.1. ✅ 责任链设计模式定义要点:
项目 |
内容 |
目的 |
将请求的发送者与接收者解耦,让多个对象有机会处理请求。 |
结构 |
每个处理者持有对下一个处理者的引用,形成链式结构。 |
核心机制 |
请求沿链传递,直到被某个处理者处理为止。 |
关键点 |
不关心请求由谁处理,处理器职责明确,链条可灵活组合。 |
1.1.2. ✅ UML 类图核心角色:
- Handler(抽象处理者):定义处理请求的接口,维护下一个处理者引用。
- ConcreteHandler(具体处理者):实现处理逻辑,判断是否处理请求,否则传递。
- Client(客户端):构建责任链并发起请求。
1.1.3. ✅ 示例场景说明(以风控为例):
风控系统中,一条贷款申请请求需要依次经过:
黑名单检查 → 信用评分检查 → 欺诈风险检查 → 额度判断
每个检查环节都是一个责任节点,最终链式组合处理整个申请流程。
2. 责任链设计模式结构
2.1. 责任链设计模式类图
- 处理者 (Handler) 声明了所有具体处理者的通用接口。
- 基础处理者 (Base Handler) 是一个可选的类, 你可以将所有处理者共用的样本代码放置在其中。
- 具体处理者 (Concrete Handlers) 包含处理请求的实际代码。 每个处理者接收到请求后, 都必须决定是否进行处理, 以及是否沿着链传递请求。
- 客户端 (Client) 可根据程序逻辑一次性或者动态地生成链。 值得注意的是, 请求可发送给链上的任意一个处理者, 而非必须是第一个处理者。
3. 责任链设计模式实现方式
责任链设计模式的实现方式有两种主要形式:链式引用方式 和 集合遍历方式。在 Java 和 Spring 项目中,两种方式都可以灵活使用,以下是详细实现说明:
3.1. ✅ 链式引用方式(经典责任链)
3.1.1. 定义抽象处理器
public abstract class RiskHandler {
protected RiskHandler next;
public void setNext(RiskHandler next) {
this.next = next;
}
public void handle(Request request) {
if (doHandle(request) && next != null) {
next.handle(request);
}
}
protected abstract boolean doHandle(Request request);
}
3.1.2. 实现具体处理器
@Component
public class BlacklistHandler extends RiskHandler {
@Override
protected boolean doHandle(Request request) {
System.out.println("黑名单校验");
// 模拟通过
return true;
}
}
@Component
public class CreditScoreHandler extends RiskHandler {
@Override
protected boolean doHandle(Request request) {
System.out.println("信用评分校验");
return true;
}
}
3.1.3. 构造责任链(可由 Spring 初始化)
@Component
public class RiskChainBuilder {
@Autowired
private BlacklistHandler blacklistHandler;
@Autowired
private CreditScoreHandler creditScoreHandler;
@PostConstruct
public void init() {
blacklistHandler.setNext(creditScoreHandler);
// 可继续设置下一个
}
public RiskHandler getChain() {
return blacklistHandler;
}
}
3.2. ✅ 集合遍历方式(策略+责任链)
这种方式更适合使用 Spring 管理 Bean。
3.2.1. 定义统一接口
public interface RiskHandler {
boolean handle(Request request);
}
3.2.2. 实现多个处理器(用注解自动注入)
@Component
public class BlacklistHandler implements RiskHandler {
public boolean handle(Request request) {
System.out.println("黑名单处理");
return true;
}
}
@Component
public class CreditHandler implements RiskHandler {
public boolean handle(Request request) {
System.out.println("信用处理");
return true;
}
}
3.2.3. 责任链执行器
@Component
public class RiskChainExecutor {
@Autowired
private List<RiskHandler> handlers;
public void process(Request request) {
for (RiskHandler handler : handlers) {
if (!handler.handle(request)) {
break; // 拦截处理
}
}
}
}
3.3. ✅ 责任链实现方式总结
项目 |
链式引用方式 |
集合遍历方式 |
Spring友好 |
较差,需要手动串联 |
非常友好,自动注入 List |
动态配置顺序 |
不方便(写死在代码) |
可通过 |
灵活性 |
灵活,可动态组合链 |
更适合顺序一致、处理流程清晰 |
推荐程度 |
简单链条推荐使用 |
企业级风控强烈推荐 |
4. 责任链设计模式适合场景
4.1. ✅ 适合使用责任链设计模式的场景
场景 |
说明 |
多个对象可以处理同一请求 |
请求的处理者不唯一,多个处理器具备处理能力。 |
处理逻辑具有先后顺序且可拆分 |
如风控流程、审批流程、日志处理、事件流转等。 |
希望动态添加或修改处理逻辑链 |
支持运行时动态组合处理器链条,提高灵活性。 |
解耦请求与处理器之间的关系 |
请求发送者无需知道谁会处理,只需交给链处理。 |
处理节点对请求是否继续传递有决策权 |
允许部分处理节点终止请求,如认证失败即停止。 |
4.2. ❌ 不适合使用责任链设计模式的场景
场景 |
原因 |
处理流程固定,结构简单 |
使用责任链会增加结构复杂度,得不偿失。 |
必须同时执行所有处理逻辑,不允许中断 |
责任链是短路模型(遇到失败可中断),不适合要求“全部执行”的场景。 |
处理者之间高度耦合或依赖上下文共享 |
处理节点应独立,依赖过多会降低可维护性。 |
对性能要求极高、链条很长 |
每次请求都需遍历链条,可能带来额外性能损耗。 |
请求必须同时由多个处理器并行处理 |
责任链是串行模式,不适合并行处理场景。 |
4.3. 📌 实际应用建议
使用责任链的条件 |
建议 |
节点解耦 + 处理器独立 + 顺序可变 |
✅ 可考虑使用 |
所有处理器必须全执行,顺序固定 |
❌ 不推荐,改用责任集(全执行)或责任调度中心 |
所有逻辑都写死在 if-else 中 |
✅ 可用责任链重构,提高扩展性和可维护性 |
5. 责任链设计模式实战示例
5.1. ✅ 应用场景:信贷申请风控校验
系统在用户提交借款申请时,需要依次执行以下校验逻辑(处理链):
- 黑名单校验
- 实名认证校验
- 信用评分校验
5.2. 🧩 请求对象
public class LoanRequest {
private String userId;
private String name;
private int age;
// 其他信息
// getter/setter省略
}
5.3. 🧩 风控处理器接口
public interface RiskHandler {
/**
* 返回 true 表示通过校验,继续执行后续处理器;false 表示终止处理。
*/
boolean handle(LoanRequest request);
}
5.4. 🧩 风控处理器实现(举例4个)
5.4.1. 🔹 黑名单校验器
@Component
@Order(1)
public class BlacklistHandler implements RiskHandler {
@Override
public boolean handle(LoanRequest request) {
System.out.println("黑名单校验: " + request.getUserId());
// 假设用户不在黑名单中
return true;
}
}
5.4.2. 🔹 实名认证校验器
@Component
@Order(2)
public class RealNameHandler implements RiskHandler {
@Override
public boolean handle(LoanRequest request) {
System.out.println("实名认证校验: " + request.getName());
return true;
}
}
5.4.3. 🔹 信用评分校验器
@Component
@Order(3)
public class CreditScoreHandler implements RiskHandler {
@Override
public boolean handle(LoanRequest request) {
System.out.println("信用评分校验: " + request.getUserId());
return true;
}
}
5.4.4. 🔹 反欺诈规则校验器
@Component
@Order(4)
public class AntiFraudHandler implements RiskHandler {
@Override
public boolean handle(LoanRequest request) {
System.out.println("反欺诈校验: " + request.getUserId());
return true;
}
}
5.5. 🧩 风控责任链执行器(接口变实现遍历)
@Component
public class RiskCheckExecutor {
@Autowired
private List<RiskHandler> handlers;
public boolean execute(LoanRequest request) {
for (RiskHandler handler : handlers) {
if (!handler.handle(request)) {
System.out.println("风控拦截,终止流程");
return false;
}
}
System.out.println("所有风控校验通过");
return true;
}
}
@Order
确保处理器执行顺序一致。
5.6. 🧩 测试调用示例(如用于 Controller)
@RestController
@RequestMapping("/loan")
public class LoanController {
@Autowired
private RiskCheckExecutor executor;
@PostMapping("/apply")
public ResponseEntity<String> apply(@RequestBody LoanRequest request) {
boolean pass = executor.execute(request);
if (pass) {
return ResponseEntity.ok("风控通过,进入审批");
} else {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("风控未通过");
}
}
}
5.7. ✅ 项目示例总结
特性 |
说明 |
注解注入 |
使用 |
避免构造函数 |
所有注入均为字段注入,无需构造器方式 |
解耦结构 |
每个处理器职责单一,互不干扰 |
可扩展性 |
增加校验逻辑仅需新增实现类并加上 |