📌 PDF :AI人工智能 --- 大模型微调与部署实战项目
大白话说Java设计模式-46-责任链模式(业务实战篇):大白商城风控/审批的"链式处理"
📌 一句话本质:责任链模式就是"多个 handler 串联",请求沿链传递,每个 handler 处理一部分,可中断可继续。
🏷️ 标签:责任链模式 / Java 设计模式 / 链式处理 / 风控审批 / 大白商城 🎯 适合:初中级后端 / 经常被"多步骤处理"困扰的工程师
目录
- 一、业务场景引入:为什么需要"链式处理"?
- 二、反面教材:硬编码多步处理的"灾难现场"
- [三、模式原理:责任链的"Handler + Chain"](#三、模式原理:责任链的"Handler + Chain")
- 四、实战代码:大白商城风控链完整实现
- [五、责任链 vs 策略 / 状态模式](#五、责任链 vs 策略 / 状态模式)
- [六、Servlet Filter 怎么用责任链?](#六、Servlet Filter 怎么用责任链?)
- [七、Spring Interceptor 怎么借鉴责任链?](#七、Spring Interceptor 怎么借鉴责任链?)
- [八、工程决策 Checklist](#八、工程决策 Checklist)
- 九、与其他模式协作
- [十、本篇小结 + 下篇预告](#十、本篇小结 + 下篇预告)
一、业务场景引入:为什么需要"链式处理"?
大白商城 2024 年风控系统遇到一个经典问题:
"订单支付前要经过 5 步风控校验(黑名单/限频/反欺诈/合规/风控拦截),加新规则要改风控代码!"
我打开代码一看:
java
/**
* ❌ 大白商城老的风控代码
*/
public class RiskControlServiceV0 {
public boolean check(Order order) {
// ❌ 硬编码 5 步
if (isBlackList(order.getUserId())) {
return false;
}
if (isOverFrequency(order.getUserId())) {
return false;
}
if (isFraud(order)) {
return false;
}
if (isCompliance(order)) {
return false;
}
if (isHighRisk(order)) {
return false;
}
return true;
}
}
这种代码的痛点:
| 序号 | 问题 | 后果 |
|---|---|---|
| ① | 加新规则改老代码 | 改 1 处牵动全身 |
| ② | 规则顺序难调整 | 改顺序要改代码 |
| ③ | 规则可配置差 | 运营不能配 |
| ④ | 单测复杂 | 要测 5 步 |
老板要的"加新规则只加 1 个类",怎么搞?
答案就是------责任链模式。
1.1 大白话讲透责任链
继续打比方:
场景:订单要经过 5 步风控校验。
- 错误做法:5 步硬编码在一个方法里
- 正确做法 :
- 每步校验封装为独立 Handler
- Handler 沿链传递请求
- 每个 Handler 处理后决定是否继续
- 加新规则?只加 1 个 Handler
责任链 = 多个 Handler 串联,请求沿链传递,每个 Handler 处理一部分。
1.2 责任链模式的 3 个真实场景
大白商城里,责任链模式用在:
| 场景 | "Handler 链" |
|---|---|
| 风控校验 | 黑名单/限频/反欺诈/合规/拦截 |
| 优惠计算 | 满减/折扣/立减/优惠券/积分 |
| 审批流程 | 主管/经理/总监/CEO |
| Servlet Filter | 鉴权/日志/压缩/缓存 |
| Spring Interceptor | 鉴权/日志/性能监控 |
任何"多步骤链式处理"的场景,都用责任链。
二、反面教材:硬编码多步处理的"灾难现场"
我们看 4 个反面教材。
2.1 反面教材 v1:if-else 堆叠
java
/**
* ❌ 反面教材 v1:if-else 堆叠
*/
if (isBlackList(userId)) return false;
if (isOverFrequency(userId)) return false;
// 5 个 if
翻车现场:
| 序号 | 问题 | 后果 |
|---|---|---|
| ① | 加新规则改代码 | 改老代码 |
| ② | 顺序难调 | 改顺序要改代码 |
2.2 反面教材 v2:Array 存 handler
java
/**
* ❌ 反面教材 v2:Array 存 handler
*/
RiskHandler[] handlers = { blackListHandler, freqHandler, fraudHandler };
for (RiskHandler h : handlers) {
if (!h.check(order)) return false;
}
翻车现场:
| 序号 | 问题 | 后果 |
|---|---|---|
| ① | Array 写死 | 加新规则要改类 |
| ② | 可配置差 | 改顺序要改代码 |
2.3 反面教材 v3:完全分散
java
/**
* ❌ 反面教材 v3:完全分散
*/
public class BlackListService { ... }
public class FrequencyService { ... }
// 5 个独立服务
翻车现场:
| 序号 | 问题 | 后果 |
|---|---|---|
| ① | 没有链 | 业务方自己串 |
| ② | 顺序难管 | 业务方记得顺序 |
2.4 反面教材 v4:完全没抽象
java
/**
* ❌ 反面教材 v4:完全没抽象
*/
public class RiskServiceV4 {
public void process() {
// 1000 行所有逻辑
}
}
2.5 共同病根
| 痛点 | 能不能解决? |
|---|---|
| 加新规则不动老代码 | ❌ 全部要改 |
| 顺序灵活 | ❌ 全部写死 |
| 规则可配置 | ❌ 全部硬编码 |
| 独立测试 | ❌ 全部耦合 |
必须上责任链。
三、模式原理:责任链的"Handler + Chain"
3.1 责任链的 2 个核心概念
Handler(处理者):
- 处理请求
- 决定是否继续
- 设置下一个 Handler
Chain(链):
- 串起所有 Handler
- 决定顺序
- 中断 / 继续
大白商城例子:
| 概念 | 例子 |
|---|---|
| Handler | BlackListHandler / FrequencyHandler / FraudHandler |
| Chain | RiskControlChain |
| 请求 | Order |
| 响应 | boolean(通过/拦截) |
3.2 责任链的 3 个核心角色
| 角色 | 职责 | 例子 |
|---|---|---|
| 抽象 Handler | 定义处理接口 | RiskHandler |
| 具体 Handler | 实现具体处理 | BlackListHandler |
| 链 | 串起 Handler | RiskControlChain |
3.3 一张图看懂责任链
OrderRequest
↓
RiskControlChain
│
│ 第 1 步
↓
BlackListHandler
│ 通过?
├── 否 → return REJECTED
└── 是 → next
↓
FrequencyHandler
│ 通过?
├── 否 → return REJECTED
└── 是 → next
↓
FraudHandler
│ ...
↓
ComplianceHandler
│ ...
↓
HighRiskHandler
│ 通过?
├── 否 → return REJECTED
└── 是 → return APPROVED
3.4 责任链的"灵魂三问"
Q1:责任链 vs 策略,区别是什么?
答:
- 责任链 :多个 Handler 串联(多步处理)
- 策略 :单个算法选择(一种算法)
- 责任链多步顺序处理 ,策略单步选算法
- 责任链强调"流程",策略强调"选择"
Q2:责任链 vs 状态模式,区别是什么?
答:
- 责任链 :链式处理(每步独立)
- 状态 :状态机(状态间转换)
- 责任链每步可中断 ,状态自动转换
- 责任链强调"流程",状态强调"转换"
Q3:责任链模式的核心价值是什么?
答:
- 解耦请求和处理(请求不知道有谁处理)
- 可动态配置(Handler 顺序灵活)
- 可中断(任意 Handler 可终止)
- 可独立测试(Handler 独立测试)
3.5 责任链的 3 种实现方式
| 方式 | 特点 | 适用 |
|---|---|---|
| Handler 持有 next | 经典 | 简单 |
| List + 遍历 | 链 | 灵活 |
| Spring Interceptor | 框架级 | Web |
大白商城主推 List + 遍历方式(可配置)。
四、实战代码:大白商城风控链完整实现
下面是大白商城生产环境在用的责任链实现,全套代码可直接复制到 IDEA 跑。
4.1 项目环境与依赖
pom.xml:
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
<relativePath/>
</parent>
<groupId>com.dabai.mall</groupId>
<artifactId>mall-design-pattern-46</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>mall-design-pattern-46</name>
<description>大白商城 - 设计模式 46 责任链模式</description>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
4.2 抽象 Handler:RiskHandler
java
package com.dabai.mall.chain;
import com.dabai.mall.chain.RiskContext.RiskResult;
/**
* ✅ 抽象 Handler:风控处理者
*
* @author 大白商城技术团队
*/
public interface RiskHandler {
/**
* ✅ 处理
*/
void handle(RiskContext context, RiskChain chain);
}
4.3 上下文:RiskContext
java
package com.dabai.mall.chain;
import lombok.Data;
import java.math.BigDecimal;
/**
* ✅ 上下文:风控请求
*/
@Data
public class RiskContext {
private String userId;
private String orderId;
private BigDecimal amount;
private String paymentChannel;
private String userLevel;
/**
* 拒绝原因
*/
private String rejectReason;
/**
* 风控结果
*/
@lombok.Data
public static class RiskResult {
private boolean approved;
private String reason;
public static RiskResult approved() {
RiskResult r = new RiskResult();
r.approved = true;
return r;
}
public static RiskResult rejected(String reason) {
RiskResult r = new RiskResult();
r.approved = false;
r.reason = reason;
return r;
}
}
}
4.4 链:RiskChain
java
package com.dabai.mall.chain;
import com.dabai.mall.chain.RiskContext.RiskResult;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* ✅ 链:风控链
* <p>
* 串起所有 Handler,按顺序处理
*
* @author 大白商城技术团队
*/
@Slf4j
public class RiskChain {
private final List<RiskHandler> handlers;
private int index = 0;
public RiskChain(List<RiskHandler> handlers) {
this.handlers = handlers;
}
/**
* ✅ 处理入口
*/
public RiskResult process(RiskContext context) {
// ✅ 调用下一个 Handler
return next(context);
}
/**
* ✅ 继续下一个 Handler
*/
public RiskResult next(RiskContext context) {
if (index >= handlers.size()) {
return RiskResult.approved();
}
RiskHandler handler = handlers.get(index++);
log.info("【风控链】执行: {}", handler.getClass().getSimpleName());
handler.handle(context, this);
return context.getRejectReason() == null
? RiskResult.approved()
: RiskResult.rejected(context.getRejectReason());
}
}
4.5 5 个具体 Handler
BlackListHandler:
java
package com.dabai.mall.chain.handler;
import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* ✅ Handler:黑名单
*/
@Slf4j
@Component
public class BlackListHandler implements RiskHandler {
@Override
public void handle(RiskContext context, RiskChain chain) {
// 实际:调 DB / 缓存查黑名单
boolean isBlack = false;
if (isBlack) {
log.info("【风控】黑名单拦截, userId={}", context.getUserId());
context.setRejectReason("黑名单用户");
return; // 不调 next
}
chain.next(context);
}
}
FrequencyHandler:
java
package com.dabai.mall.chain.handler;
import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* ✅ Handler:限频
*/
@Slf4j
@Component
public class FrequencyHandler implements RiskHandler {
@Override
public void handle(RiskContext context, RiskChain chain) {
// 实际:调 Redis 计数
boolean isOverFreq = false;
if (isOverFreq) {
log.info("【风控】限频拦截, userId={}", context.getUserId());
context.setRejectReason("操作过于频繁");
return;
}
chain.next(context);
}
}
FraudHandler:
java
package com.dabai.mall.chain.handler;
import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* ✅ Handler:反欺诈
*/
@Slf4j
@Component
public class FraudHandler implements RiskHandler {
@Override
public void handle(RiskContext context, RiskChain chain) {
// 实际:调反欺诈系统
boolean isFraud = false;
if (isFraud) {
log.info("【风控】反欺诈拦截, orderId={}", context.getOrderId());
context.setRejectReason("疑似欺诈交易");
return;
}
chain.next(context);
}
}
ComplianceHandler:
java
package com.dabai.mall.chain.handler;
import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* ✅ Handler:合规
*/
@Slf4j
@Component
public class ComplianceHandler implements RiskHandler {
@Override
public void handle(RiskContext context, RiskChain chain) {
// 实际:调合规检查
boolean isIllegal = false;
if (isIllegal) {
log.info("【风控】合规拦截, orderId={}", context.getOrderId());
context.setRejectReason("不符合合规要求");
return;
}
chain.next(context);
}
}
HighRiskHandler:
java
package com.dabai.mall.chain.handler;
import com.dabai.mall.chain.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
/**
* ✅ Handler:风控拦截(金额 > 1 万)
*/
@Slf4j
@Component
public class HighRiskHandler implements RiskHandler {
@Override
public void handle(RiskContext context, RiskChain chain) {
// 实际:根据金额和用户等级判断
if (context.getAmount().compareTo(new BigDecimal("10000")) > 0
&& !"VIP".equals(context.getUserLevel())) {
log.info("【风控】高金额拦截, orderId={}", context.getOrderId());
context.setRejectReason("高金额需要 VIP");
return;
}
chain.next(context);
}
}
4.6 业务调用方
java
package com.dabai.mall.service;
import com.dabai.mall.chain.*;
import com.dabai.mall.chain.RiskContext.RiskResult;
import com.dabai.mall.chain.handler.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
/**
* ✅ 风控服务:责任链模式的调用方
* <p>
* 业务方只调 chain.process(),不关心 handler 细节
*
* @author 大白商城技术团队
*/
@Service
public class RiskControlService {
@Autowired
private BlackListHandler blackListHandler;
@Autowired
private FrequencyHandler frequencyHandler;
@Autowired
private FraudHandler fraudHandler;
@Autowired
private ComplianceHandler complianceHandler;
@Autowired
private HighRiskHandler highRiskHandler;
/**
* ✅ 业务方只写一种代码
*/
public RiskResult check(RiskContext context) {
// 1️⃣ 构造链
List<RiskHandler> handlers = List.of(
blackListHandler, frequencyHandler,
fraudHandler, complianceHandler, highRiskHandler);
RiskChain chain = new RiskChain(handlers);
// 2️⃣ 启动链
return chain.process(context);
}
}
4.7 单元测试
java
package com.dabai.mall.chain;
import com.dabai.mall.chain.RiskContext.RiskResult;
import com.dabai.mall.chain.handler.*;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* 责任链模式完整单元测试
*/
class RiskChainTest {
@Test
void testAllPassed() {
RiskContext context = new RiskContext();
context.setUserId("USER_001");
context.setOrderId("ORDER_001");
context.setAmount(new BigDecimal("100"));
context.setUserLevel("VIP");
List<RiskHandler> handlers = List.of(
new BlackListHandler(),
new FrequencyHandler(),
new FraudHandler(),
new ComplianceHandler(),
new HighRiskHandler());
RiskChain chain = new RiskChain(handlers);
RiskResult result = chain.process(context);
assertTrue(result.isApproved());
}
@Test
void testHighAmountRejected() {
RiskContext context = new RiskContext();
context.setUserId("USER_001");
context.setOrderId("ORDER_001");
context.setAmount(new BigDecimal("50000")); // 高金额
context.setUserLevel("NORMAL");
List<RiskHandler> handlers = List.of(
new BlackListHandler(),
new FrequencyHandler(),
new FraudHandler(),
new ComplianceHandler(),
new HighRiskHandler());
RiskChain chain = new RiskChain(handlers);
RiskResult result = chain.process(context);
assertFalse(result.isApproved());
}
@Test
void testEmptyChain() {
// ✅ 空链直接通过
RiskChain chain = new RiskChain(List.of());
RiskContext context = new RiskContext();
RiskResult result = chain.process(context);
assertTrue(result.isApproved());
}
@Test
void testSingleHandler() {
// ✅ 单个 handler
RiskChain chain = new RiskChain(List.of(new BlackListHandler()));
RiskContext context = new RiskContext();
RiskResult result = chain.process(context);
assertTrue(result.isApproved());
}
@Test
void testHandlerShortCircuit() {
// ✅ Handler 中断
List<RiskHandler> handlers = List.of(
new BlackListHandler(),
new HighRiskHandler());
RiskChain chain = new RiskChain(handlers);
RiskContext context = new RiskContext();
context.setAmount(new BigDecimal("50000"));
// 第一个通过,第二个拒绝
RiskResult result = chain.process(context);
assertFalse(result.isApproved());
}
}
五、责任链 vs 策略 / 状态模式
5.1 一张表看清区别
| 模式 | 关注点 | 处理 | 适用 |
|---|---|---|---|
| 责任链 | 多步链式 | 多 Handler | 风控/审批 |
| 策略 | 算法选择 | 单一算法 | 多种算法 |
| 状态 | 状态机 | 自动转换 | 行为随状态变 |
5.2 决策树
多步骤处理?
├── 是
│ ├── 步骤可中断?
│ │ ├── 是 → ✅ 责任链
│ │ └── 否 → 模板方法
└── 否
├── 多种算法可切换?
│ ├── 是 → ✅ 策略
│ └── 否
│ ├── 行为随状态变?
│ │ ├── 是 → ✅ 状态
│ │ └── 否 → 普通类
大白商城选型:
| 场景 | 选哪个 | 原因 |
|---|---|---|
| 风控链 | 责任链 | 5 步可中断 |
| 支付方式 | 策略 | 4 种算法 |
| 订单状态 | 状态 | 状态机 |
| 优惠计算 | 责任链 | 多规则组合 |
六、Servlet Filter 怎么用责任链?
6.1 Filter:经典责任链
核心源码:
java
/**
* ✅ Servlet Filter
*/
public interface Filter {
void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
}
使用:
java
/**
* ✅ 鉴权 Filter
*/
@Component
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 1️⃣ 鉴权
if (!authenticate(request)) {
response.getWriter().write("Unauthorized");
return;
}
// 2️⃣ 继续
chain.doFilter(request, response);
}
}
关键点:
| 关键点 | 解释 |
|---|---|
FilterChain |
责任链 |
doFilter() |
继续 |
| 不调 | 中断 |
6.2 FilterChain:链
java
/**
* ✅ Filter 链
*/
public interface FilterChain {
void doFilter(ServletRequest var1, ServletResponse var2)
throws IOException, ServletException;
}
6.3 大白商城的"抄作业"
java
/**
* 借鉴 Filter:业务 Handler
*/
public interface BusinessHandler {
void handle(BusinessContext context, BusinessChain chain);
}
七、Spring Interceptor 怎么借鉴责任链?
7.1 HandlerInterceptor:Spring 拦截器
核心源码:
java
/**
* ✅ Spring 拦截器
*/
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, ...) { return true; }
default void postHandle(...) { ... }
default void afterCompletion(...) { ... }
}
使用:
java
/**
* ✅ 鉴权拦截器
*/
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, ...) {
if (!authenticate(request)) {
return false; // 中断
}
return true; // 继续
}
}
注册:
java
/**
* ✅ 拦截器注册
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**");
}
}
7.2 InterceptorRegistry:链
Spring 内部用 HandlerExecutionChain 串起所有拦截器:
java
/**
* ✅ 拦截器链
*/
public class HandlerExecutionChain {
private final Object handler;
private final List<HandlerInterceptor> interceptors = new ArrayList<>();
boolean applyPreHandle(HttpServletRequest request, ...) {
for (HandlerInterceptor interceptor : interceptors) {
if (!interceptor.preHandle(request, ...)) {
return false;
}
}
return true;
}
}
7.3 大白商城的"抄作业"
java
/**
* 借鉴 Spring Interceptor:业务拦截器
*/
public interface BusinessInterceptor {
boolean preHandle(BusinessContext context);
void postHandle(BusinessContext context);
void afterCompletion(BusinessContext context);
}
八、工程决策 Checklist
8.1 ✅ 这 5 种情况,强烈建议用责任链
| 序号 | 场景 | 原因 |
|---|---|---|
| ① | 多步骤处理 | 风控/审批 |
| ② | 步骤可中断 | 任一可拒绝 |
| ③ | 顺序灵活 | 可调整 |
| ④ | Handler 独立 | 单元测试 |
| ⑤ | 加新规则 | 不改老代码 |
8.2 ❌ 这 5 种情况,绝对不要用责任链
| 序号 | 场景 | 原因 |
|---|---|---|
| ① | 只有 1 步 | 直接调 |
| ② | 步骤不可中断 | 用模板 |
| ③ | 业务简单 | 过度设计 |
| ④ | 追求简单 | 类多 |
| ⑤ | 步骤固定 | 硬编码 |
8.3 ⚠️ 责任链的 6 大常见坑
| 序号 | 坑 | 表现 | 解决方案 |
|---|---|---|---|
| ① | 链过长 | 性能差 | 控制长度 |
| ② | Handler 顺序 | 顺序错 | 配置 |
| ③ | 忘记 next | 中断 | 模板 |
| ④ | 状态污染 | Handler 之间 | 隔离 |
| ⑤ | 异常处理 | 中断 | 统一 |
| ⑥ | 循环引用 | 死循环 | 检测 |
8.4 面试官视角:责任链高频追问
Q1:责任链 vs 策略,区别是什么?
答:责任链多步链式处理 (可中断),策略单步算法选择 。责任链强调"流程",策略强调"选择"。
Q2:责任链模式的核心价值是什么?
答:解耦请求和处理 + 可动态配置 + 可中断。请求不知道有谁处理,加新 Handler 不改老代码。
Q3:Servlet Filter 怎么用责任链?
答:Filter 调
chain.doFilter()继续,不调则中断。多个 Filter 组成 FilterChain ,经典责任链。
九、与其他模式协作
9.1 责任链 + 策略 = 链中用策略
java
/**
* ✅ 责任链 + 策略:Handler 内用策略
*/
public class FraudHandler implements RiskHandler {
@Autowired
private FraudCheckStrategy strategy; // 策略
@Override
public void handle(RiskContext context, RiskChain chain) {
if (strategy.check(context)) {
context.setRejectReason("疑似欺诈");
return;
}
chain.next(context);
}
}
9.2 责任链 + 模板方法 = 链中用模板
9.3 责任链 + 状态 = 链中用状态
9.4 大白商城模式协作全景图
┌──────────────┐
│ 责任链 │ ← 本篇
└──────┬───────┘
│
┌───────────┬───────┼───────┬───────────┐
│ │ │ │ │
┌───▼───┐ ┌────▼───┐ ┌▼────┐ ┌▼─────┐ ┌───▼────┐
│策略 │ │模板方法│ │状态 │ │命令 │ │ 装饰器 │
│(链内) │ │(骨架) │ │(机) │ │(动作)│ │(增强) │
└───────┘ └────────┘ └──────┘ └──────┘ └───────┘
26 篇 28 篇 32 篇 34 篇 16 篇
十、本篇小结 + 下篇预告
10.1 本篇小结(5 个核心要点)
- 本质 :责任链 = 多 Handler 串联 ,每步可中断。
- 场景 :风控/审批/优惠计算/Servlet Filter,多步骤处理。
- 对比:责任链 vs 策略(多步 vs 单步)/ 责任链 vs 状态(流程 vs 转换)。
- Servlet Filter :
chain.doFilter()经典实现。 - 避坑:链过长 / 顺序错 / 忘记 next / 状态污染。
10.2 一句话总结
责任链不是"换种方式写多步 if-else",是"用 Handler 链解耦请求和处理" 。大白商城从 5 步硬编码 → 5 个 Handler 串成链------加新风控规则只加 1 个 Handler,顺序可配置,规则可中断。
10.3 知识脑图
责任链模式
├── 2 个核心概念
│ ├── Handler(处理者)
│ └── Chain(链)
├── 3 大角色
│ ├── 抽象 Handler(RiskHandler)
│ ├── 具体 Handler(5 个)
│ └── 链(RiskChain)
├── 5 个具体 Handler
│ ├── BlackListHandler(黑名单)
│ ├── FrequencyHandler(限频)
│ ├── FraudHandler(反欺诈)
│ ├── ComplianceHandler(合规)
│ └── HighRiskHandler(高金额)
├── 模式对比
│ ├── vs 策略(多步 vs 单步)
│ ├── vs 状态(流程 vs 转换)
│ └── vs 模板(可中断 vs 不可中断)
├── Servlet Filter
│ ├── Filter 接口
│ ├── FilterChain
│ └── doFilter 继续
├── Spring Interceptor
│ ├── HandlerInterceptor
│ ├── InterceptorRegistry
│ └── HandlerExecutionChain
└── 模式协作
├── + 策略(链内用策略)
├── + 模板(链中用模板)
└── + 状态(链中用状态)
10.4 下篇预告
第 47 篇【责任链模式 - 源码剖析篇】:JDK / Spring 中的责任链实现
下一篇我们会深入源码,回答三个问题:
- Servlet Filter 怎么用责任链?
- Spring Interceptor 怎么用责任链?
- Netty Pipeline 怎么用责任链?
并附完整的源码解读 + 流程图 + 大白商城的"抄作业"实践。
觉得对您有帮助,麻烦 点点关注啦 ,您的关注是我创作的最大动力~ 🎯