责任链模式:设计与实践
一、什么是责任链模式
1. 基本定义
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,由《设计模式:可复用面向对象软件的基础》(GOF著作)定义为:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
该模式通过构建一个对象处理链,将请求的发送者与接收者解耦,请求在链中依次传递,每个接收者可选择处理请求或传递给下一个接收者,直至请求被处理或到达链的末端。核心是将“请求处理”与“请求分发”分离,允许动态调整处理顺序和参与者。
2. 核心思想
责任链模式的核心在于请求的链式传递与处理。当系统中存在多个对象可以处理同一类型请求,且具体处理者不确定(需动态决定)时,通过将这些对象组成一条链,使请求能够沿着链传递,每个对象都有机会处理请求。这种设计既避免了请求发送者与多个处理者的直接耦合,又允许灵活调整处理链的结构(如增加、移除或重排处理者),从而适应不同的业务场景。
二、责任链模式的特点
1. 链式结构
多个处理者组成链式结构,请求沿链传递,每个处理者只知道链中的下一个处理者。
2. 动态传递
请求在链中依次传递,直到被某个处理者处理或到达链的末端,处理者无需知道请求的整体传递路径。
3. 职责分离
每个处理者只负责自己职责范围内的请求处理,不处理的请求将传递给下一个处理者,符合单一职责原则。
4. 灵活调整
可动态增加、移除或调整处理者的顺序,无需修改请求发送者和其他处理者的代码,符合开闭原则。
5. 可能存在未处理
若链中所有处理者都不处理请求,该请求将未被处理,需考虑默认处理机制。
| 特点 | 说明 |
|---|---|
| 链式结构 | 处理者组成链条,请求沿链传递 |
| 动态传递 | 请求依次经过处理者,直至被处理或终结 |
| 职责分离 | 每个处理者仅处理自身职责范围内的请求 |
| 灵活调整 | 可动态增删或重排处理者,扩展性强 |
| 可能存在未处理 | 若所有处理者都不处理,请求将未被处理 |
三、责任链模式的标准代码实现
1. 模式结构
责任链模式包含三个核心角色:
- 抽象处理者(Handler):定义处理请求的接口,包含一个指向 nextHandler(下一个处理者)的引用。
- 具体处理者(ConcreteHandler):实现抽象处理者接口,处理自己职责范围内的请求,若无法处理则传递给下一个处理者。
- 客户端(Client):创建处理链并发送请求,无需关心请求的具体处理者。
2. 代码实现示例
2.1 抽象处理者
/**
* 抽象处理者
* 定义处理请求的接口和链式引用
*/
public abstract class Handler {
// 下一个处理者
protected Handler nextHandler;
// 设置下一个处理者
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
// 处理请求的抽象方法(由子类实现)
public abstract void handleRequest(Request request);
}
2.2 请求模型
/**
* 请求模型
* 包含请求类型和内容
*/
public class Request {
private String type; // 请求类型(如"TYPE_A"、"TYPE_B")
private String content; // 请求内容
private int level; // 请求级别(用于分级处理)
// 构造器、getter和setter
public Request(String type, String content, int level) {
this.type = type;
this.content = content;
this.level = level;
}
public String getType() { return type; }
public String getContent() { return content; }
public int getLevel() { return level; }
}
2.3 具体处理者
/**
* 具体处理者1:处理低级别的请求
*/
public class LowLevelHandler extends Handler {
private static final int MAX_LEVEL = 3; // 处理1-3级请求
@Override
public void handleRequest(Request request) {
if (request.getLevel() <= MAX_LEVEL) {
// 处理请求
System.out.printf("LowLevelHandler处理请求:类型=%s,内容=%s,级别=%d%n",
request.getType(), request.getContent(), request.getLevel());
} else if (nextHandler != null) {
// 无法处理,传递给下一个处理者
nextHandler.handleRequest(request);
} else {
// 无下一个处理者,请求未被处理
System.out.printf("LowLevelHandler无法处理请求,级别=%d%n", request.getLevel());
}
}
}
/**
* 具体处理者2:处理中等级别的请求
*/
public class MiddleLevelHandler extends Handler {
private static final int MAX_LEVEL = 6; // 处理4-6级请求
@Override
public void handleRequest(Request request) {
if (request.getLevel() > 3 && request.getLevel() <= MAX_LEVEL) {
System.out.printf("MiddleLevelHandler处理请求:类型=%s,内容=%s,级别=%d%n",
request.getType(), request.getContent(), request.getLevel());
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.printf("MiddleLevelHandler无法处理请求,级别=%d%n", request.getLevel());
}
}
}
/**
* 具体处理者3:处理高级别的请求
*/
public class HighLevelHandler extends Handler {
private static final int MAX_LEVEL = 10; // 处理7-10级请求
@Override
public void handleRequest(Request request) {
if (request.getLevel() > 6 && request.getLevel() <= MAX_LEVEL) {
System.out.printf("HighLevelHandler处理请求:类型=%s,内容=%s,级别=%d%n",
request.getType(), request.getContent(), request.getLevel());
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.printf("HighLevelHandler无法处理请求,级别=%d%n", request.getLevel());
}
}
}
2.4 客户端与链的构建
/**
* 客户端
* 创建责任链并发送请求
*/
public class Client {
// 构建责任链
public static Handler buildChain() {
// 创建具体处理者
Handler lowHandler = new LowLevelHandler();
Handler middleHandler = new MiddleLevelHandler();
Handler highHandler = new HighLevelHandler();
// 设置处理链顺序:低→中→高
lowHandler.setNextHandler(middleHandler);
middleHandler.setNextHandler(highHandler);
// 返回链的起始处理者
return lowHandler;
}
public static void main(String[] args) {
// 构建责任链
Handler chain = buildChain();
// 发送不同级别的请求
System.out.println("=== 发送1级请求 ===");
chain.handleRequest(new Request("TYPE_A", "普通查询", 1));
System.out.println("\n=== 发送5级请求 ===");
chain.handleRequest(new Request("TYPE_B", "重要操作", 5));
System.out.println("\n=== 发送8级请求 ===");
chain.handleRequest(new Request("TYPE_C", "紧急操作", 8));
System.out.println("\n=== 发送12级请求(超出最大级别) ===");
chain.handleRequest(new Request("TYPE_D", "超纲操作", 12));
}
}
3. 代码实现特点总结
| 角色 | 核心职责 | 代码特点 |
|---|---|---|
| 抽象处理者(Handler) | 定义处理接口和链式引用 | 声明handleRequest()方法,包含nextHandler字段和setNextHandler()方法 |
| 具体处理者(ConcreteHandler) | 处理职责范围内的请求,否则传递给下一个处理者 | 实现handleRequest()方法,判断是否处理请求,若不处理则调用nextHandler.handleRequest() |
| 客户端(Client) | 构建处理链并发送请求 | 创建处理者实例,设置链的顺序,调用链的起始处理者处理请求,不关心具体处理过程 |
四、支付框架设计中责任链模式的运用
以支付订单的多维度校验为例,说明责任链模式在支付系统中的具体实现:
1. 场景分析
支付系统在创建支付订单前,需要对订单信息进行多维度校验,典型校验环节包括:
- 参数校验:检查订单号、金额、商户ID等必填参数是否完整有效(如金额不能为负)
- 风控校验:验证订单是否存在风险(如黑名单用户、异常IP地址、可疑交易模式)
- 限额校验:检查是否超过用户单日支付限额、商户单笔交易限额
- 渠道校验:确认所选支付渠道支持当前订单类型(如信用卡是否支持大额支付)
这些校验环节逻辑独立但执行顺序固定,若将所有校验逻辑硬编码在订单服务中,会导致代码臃肿、耦合严重,新增或修改校验规则需改动核心代码。使用责任链模式可将每个校验环节封装为具体处理者,形成校验链,订单请求沿链传递,任一环节校验失败则终止流程,全部通过则进入支付流程。
2. 设计实现
2.1 抽象处理者与请求模型
import java.math.BigDecimal;
/**
* 订单校验处理者接口
*/
public interface OrderValidator {
/**
* 设置下一个校验者
*/
void setNext(OrderValidator next);
/**
* 执行校验
* @return 校验结果(包含是否通过和失败原因)
*/
ValidationResult validate(PaymentOrder order);
}
/**
* 校验结果模型
*/
public class ValidationResult {
private boolean passed; // 是否通过
private String message; // 失败原因(通过时可为null)
// 静态工厂方法
public static ValidationResult success() {
return new ValidationResult(true, null);
}
public static ValidationResult fail(String message) {
return new ValidationResult(false, message);
}
// 构造器、getter
private ValidationResult(boolean passed, String message) {
this.passed = passed;
this.message = message;
}
public boolean isPassed() { return passed; }
public String getMessage() { return message; }
}
/**
* 支付订单模型
*/
public class PaymentOrder {
private String orderId; // 订单ID
private BigDecimal amount; // 支付金额
private String merchantId; // 商户ID
private String userId; // 用户ID
private String channelCode; // 支付渠道编码
private String ip; // 客户端IP地址
private String currency; // 币种
// getter和setter
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }
public BigDecimal getAmount() { return amount; }
public void setAmount(BigDecimal amount) { this.amount = amount; }
public String getMerchantId() { return merchantId; }
public String getUserId() { return userId; }
public String getIp() { return ip; }
public String getChannelCode() { return channelCode; }
}
2.2 具体校验处理者
/**
* 具体处理者1:参数校验
*/
public class ParamValidator implements OrderValidator {
private OrderValidator next;
@Override
public void setNext(OrderValidator next) {
this.next = next;
}
@Override
public ValidationResult validate(PaymentOrder order) {
// 1. 检查必填参数
if (order.getOrderId() == null || order.getOrderId().isEmpty()) {
return ValidationResult.fail("订单号不能为空");
}
if (order.getMerchantId() == null || order.getMerchantId().isEmpty()) {
return ValidationResult.fail("商户ID不能为空");
}
// 2. 检查金额有效性
BigDecimal amount = order.getAmount();
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
return ValidationResult.fail("支付金额必须大于0");
}
// 3. 参数校验通过,传递给下一个校验者
if (next != null) {
return next.validate(order);
}
return ValidationResult.success();
}
}
/**
* 具体处理者2:风控校验
*/
public class RiskValidator implements OrderValidator {
private OrderValidator next;
private RiskService riskService; // 风控服务(依赖注入)
@Override
public void setNext(OrderValidator next) {
this.next = next;
}
@Override
public ValidationResult validate(PaymentOrder order) {
// 1. 检查用户是否在黑名单中
if (riskService.isBlacklisted(order.getUserId())) {
return ValidationResult.fail("用户在黑名单中,拒绝交易");
}
// 2. 检查IP地址是否异常
if (riskService.isAbnormalIp(order.getIp())) {
return ValidationResult.fail("IP地址异常,拒绝交易");
}
// 3. 检查交易模式是否可疑
if (riskService.isSuspicious(order)) {
return ValidationResult.fail("交易模式可疑,已触发风控");
}
// 4. 风控校验通过,传递给下一个校验者
if (next != null) {
return next.validate(order);
}
return ValidationResult.success();
}
}
/**
* 具体处理者3:限额校验
*/
public class LimitValidator implements OrderValidator {
private OrderValidator next;
private LimitService limitService; // 限额服务(依赖注入)
@Override
public void setNext(OrderValidator next) {
this.next = next;
}
@Override
public ValidationResult validate(PaymentOrder order) {
// 1. 检查用户单日限额
BigDecimal dailyUsed = limitService.getUserDailyUsed(order.getUserId());
BigDecimal dailyLimit = limitService.getUserDailyLimit(order.getUserId());
if (dailyUsed.add(order.getAmount()).compareTo(dailyLimit) > 0) {
return ValidationResult.fail("超过用户单日支付限额:" + dailyLimit);
}
// 2. 检查商户单笔限额
BigDecimal merchantSingleLimit = limitService.getMerchantSingleLimit(order.getMerchantId());
if (order.getAmount().compareTo(merchantSingleLimit) > 0) {
return ValidationResult.fail("超过商户单笔交易限额:" + merchantSingleLimit);
}
// 3. 限额校验通过,传递给下一个校验者
if (next != null) {
return next.validate(order);
}
return ValidationResult.success();
}
}
/**
* 具体处理者4:渠道校验
*/
public class ChannelValidator implements OrderValidator {
private OrderValidator next;
private ChannelService channelService; // 渠道服务(依赖注入)
@Override
public void setNext(OrderValidator next) {
this.next = next;
}
@Override
public ValidationResult validate(PaymentOrder order) {
// 1. 检查渠道是否可用
if (!channelService.isAvailable(order.getChannelCode())) {
return ValidationResult.fail("支付渠道不可用:" + order.getChannelCode());
}
// 2. 检查渠道是否支持当前金额
if (!channelService.supportAmount(order.getChannelCode(), order.getAmount())) {
return ValidationResult.fail("渠道不支持该金额交易:" + order.getAmount());
}
// 3. 检查渠道是否支持当前币种
if (!channelService.supportCurrency(order.getChannelCode(), order.getCurrency())) {
return ValidationResult.fail("渠道不支持币种:" + order.getCurrency());
}
// 4. 渠道校验通过
return next != null ? next.validate(order) : ValidationResult.success();
}
}
2.3 责任链构建与使用
/**
* 订单校验链工厂
* 负责构建校验链
*/
public class ValidationChainFactory {
/**
* 构建完整的订单校验链
*/
public static OrderValidator buildFullChain() {
// 创建各校验者实例(实际项目中通过Spring注入)
OrderValidator paramValidator = new ParamValidator();
OrderValidator riskValidator = new RiskValidator();
OrderValidator limitValidator = new LimitValidator();
OrderValidator channelValidator = new ChannelValidator();
// 设置校验顺序:参数→风控→限额→渠道
paramValidator.setNext(riskValidator);
riskValidator.setNext(limitValidator);
limitValidator.setNext(channelValidator);
return paramValidator;
}
}
/**
* 支付订单服务(客户端)
*/
public class PaymentOrderService {
private OrderValidator validationChain;
// 构造器注入校验链
public PaymentOrderService(OrderValidator validationChain) {
this.validationChain = validationChain;
}
/**
* 创建支付订单(包含校验流程)
*/
public String createOrder(PaymentOrder order) {
// 1. 执行校验链
ValidationResult result = validationChain.validate(order);
if (!result.isPassed()) {
System.out.println("订单创建失败:" + result.getMessage());
return null;
}
// 2. 校验通过,创建订单(实际中会写入数据库)
System.out.println("订单校验通过,创建订单:" + order.getOrderId());
return order.getOrderId();
}
public static void main(String[] args) {
// 构建校验链
OrderValidator chain = ValidationChainFactory.buildFullChain();
PaymentOrderService service = new PaymentOrderService(chain);
// 创建测试订单
PaymentOrder order = new PaymentOrder();
order.setOrderId("PAY20240501001");
order.setAmount(new BigDecimal("2000"));
order.setMerchantId("MCH001");
order.setUserId("USER123");
order.setChannelCode("ALIPAY");
order.setIp("113.108.92.34");
order.setCurrency("CNY");
// 创建订单(触发校验)
service.createOrder(order);
}
}
3. 模式价值体现
- 职责分离:每个校验逻辑封装在独立类中,参数校验、风控、限额等逻辑互不干扰,符合单一职责原则,便于单独维护和测试
- 灵活扩展:新增校验环节(如发票校验、优惠券校验)只需添加新的
OrderValidator实现,无需修改现有校验者和订单服务,符合开闭原则 - 顺序可调:通过调整处理者的链式顺序,可灵活改变校验流程(如特殊活动期间将渠道校验提前)
- 失败定位清晰:校验结果包含具体失败原因,便于问题排查(如明确是参数错误还是风控拦截)
- 可复用性高:校验者可在不同场景中复用(如风控校验可同时用于订单创建和退款申请)
五、开源框架中责任链模式的运用
以Spring Security的过滤器链(Filter Chain) 为例,说明责任链模式在开源框架中的典型应用:
1. 核心实现分析
Spring Security是Spring生态中的安全框架,其核心功能(认证、授权、CSRF防护等)通过过滤器链实现,每个过滤器专注于单一安全功能,请求在链中依次传递,形成完整的安全校验流程。
1.1 抽象处理者(Filter)
Spring Security基于Servlet的Filter接口构建过滤器链,Filter扮演抽象处理者角色:
public interface Filter {
// 处理请求
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException;
}
FilterChain接口用于维护过滤器链的顺序和传递请求:
public interface FilterChain {
// 传递请求给下一个过滤器
void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
1.2 具体处理者(Security Filter)
Spring Security提供多种具体过滤器(具体处理者),如:
UsernamePasswordAuthenticationFilter:处理用户名密码认证CsrfFilter:处理CSRF防护FilterSecurityInterceptor:处理权限校验ExceptionTranslationFilter:处理认证/授权异常
以UsernamePasswordAuthenticationFilter为例:
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) {
// 从请求中提取用户名和密码
String username = obtainUsername(request);
String password = obtainPassword(request);
// 执行认证逻辑
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(username, password);
return this.getAuthenticationManager().authenticate(authRequest);
}
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain, Authentication authResult) {
// 认证成功后,将请求传递给下一个过滤器
chain.doFilter(request, response);
}
}
1.3 过滤器链的构建与执行
Spring Security在启动时自动构建过滤器链,请求经过链中所有过滤器处理:
// Spring Security配置示例
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin() // 启用表单登录过滤器
.and()
.csrf(); // 启用CSRF防护过滤器
}
}
请求到达时,Spring Security的FilterChainProxy作为链的入口,依次调用链中的过滤器:
CsrfFilter:验证CSRF令牌UsernamePasswordAuthenticationFilter:处理认证FilterSecurityInterceptor:验证用户权限- ...(其他过滤器)
2. 责任链模式在Spring Security中的价值
- 安全功能解耦:认证、授权、CSRF防护等功能通过独立过滤器实现,便于扩展和定制
- 灵活配置:开发者可通过配置添加、移除或重排过滤器,适应不同安全需求
- 请求拦截链:请求经过全链路安全校验,任一过滤器拦截(如认证失败)则终止流程
- 可扩展性:支持自定义过滤器(如添加验证码过滤器),无需修改框架核心代码
六、总结
1. 责任链模式的适用场景
- 当系统中存在多个对象可以处理同一类型请求,且处理顺序固定时
- 当需要动态调整请求处理者或处理顺序时
- 当请求发送者无需知道具体处理者,只需确保请求被处理时
- 当处理逻辑可拆分为多个独立环节,且每个环节仅处理部分职责时
- 当需要避免请求发送者与多个处理者之间的直接耦合时
2. 责任链模式与其他模式的区别
- 与装饰器模式:两者都使用链式结构,但装饰器模式用于动态增强对象功能,责任链模式用于请求的传递与处理,前者强调功能增强,后者强调请求分发
- 与命令模式:命令模式将请求封装为对象,责任链模式将处理者组成链,前者关注请求的封装,后者关注请求的传递
- 与观察者模式:观察者模式中多个观察者同时接收通知并独立处理,责任链模式中请求沿链传递,只有一个或零个处理者处理请求,前者是广播通知,后者是链式传递
3. 支付系统中的实践价值
- 复杂流程拆分:将支付订单校验、退款审批等复杂流程拆分为独立环节,降低系统复杂度
- 业务规则动态调整:通过调整处理链顺序,快速适应业务变化(如活动期间调整限额校验规则)
- 团队并行开发:不同处理者可由不同团队开发,减少协作成本,提高开发效率
- 故障隔离:单个处理者的异常不会影响整个链的其他处理者,提升系统稳定性
- 合规性支持:清晰的处理链便于审计和追溯,满足金融系统的合规要求
4. 实践建议
- 控制链的长度:链过长可能导致请求处理效率下降,建议不超过5-7个处理者
- 设置默认处理者:在链的末端添加默认处理者,确保所有请求都能被处理或给出明确反馈
- 避免循环依赖:确保处理链是单向链表,防止请求在链中循环传递导致死循环
- 处理者无状态化:尽量使处理者无状态,便于复用和并发处理
- 结合配置中心:通过配置中心动态调整处理链结构(如启用/禁用某处理者),无需重启服务
责任链模式通过“请求链式传递、处理者各司其职”的设计,为支付系统中复杂流程的解耦与扩展提供了优雅的解决方案。它不仅是一种代码组织模式,更是一种“分而治之”的思想,合理应用可显著提升支付系统的可维护性、灵活性和可扩展性。