责任链模式:设计与实践

24 阅读15分钟

责任链模式:设计与实践

一、什么是责任链模式

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作为链的入口,依次调用链中的过滤器:

  1. CsrfFilter:验证CSRF令牌
  2. UsernamePasswordAuthenticationFilter:处理认证
  3. FilterSecurityInterceptor:验证用户权限
  4. ...(其他过滤器)

2. 责任链模式在Spring Security中的价值

  • 安全功能解耦:认证、授权、CSRF防护等功能通过独立过滤器实现,便于扩展和定制
  • 灵活配置:开发者可通过配置添加、移除或重排过滤器,适应不同安全需求
  • 请求拦截链:请求经过全链路安全校验,任一过滤器拦截(如认证失败)则终止流程
  • 可扩展性:支持自定义过滤器(如添加验证码过滤器),无需修改框架核心代码

六、总结

1. 责任链模式的适用场景

  • 当系统中存在多个对象可以处理同一类型请求,且处理顺序固定时
  • 当需要动态调整请求处理者或处理顺序时
  • 当请求发送者无需知道具体处理者,只需确保请求被处理时
  • 当处理逻辑可拆分为多个独立环节,且每个环节仅处理部分职责时
  • 当需要避免请求发送者与多个处理者之间的直接耦合时

2. 责任链模式与其他模式的区别

  • 与装饰器模式:两者都使用链式结构,但装饰器模式用于动态增强对象功能,责任链模式用于请求的传递与处理,前者强调功能增强,后者强调请求分发
  • 与命令模式:命令模式将请求封装为对象,责任链模式将处理者组成链,前者关注请求的封装,后者关注请求的传递
  • 与观察者模式:观察者模式中多个观察者同时接收通知并独立处理,责任链模式中请求沿链传递,只有一个或零个处理者处理请求,前者是广播通知,后者是链式传递

3. 支付系统中的实践价值

  • 复杂流程拆分:将支付订单校验、退款审批等复杂流程拆分为独立环节,降低系统复杂度
  • 业务规则动态调整:通过调整处理链顺序,快速适应业务变化(如活动期间调整限额校验规则)
  • 团队并行开发:不同处理者可由不同团队开发,减少协作成本,提高开发效率
  • 故障隔离:单个处理者的异常不会影响整个链的其他处理者,提升系统稳定性
  • 合规性支持:清晰的处理链便于审计和追溯,满足金融系统的合规要求

4. 实践建议

  • 控制链的长度:链过长可能导致请求处理效率下降,建议不超过5-7个处理者
  • 设置默认处理者:在链的末端添加默认处理者,确保所有请求都能被处理或给出明确反馈
  • 避免循环依赖:确保处理链是单向链表,防止请求在链中循环传递导致死循环
  • 处理者无状态化:尽量使处理者无状态,便于复用和并发处理
  • 结合配置中心:通过配置中心动态调整处理链结构(如启用/禁用某处理者),无需重启服务

责任链模式通过“请求链式传递、处理者各司其职”的设计,为支付系统中复杂流程的解耦与扩展提供了优雅的解决方案。它不仅是一种代码组织模式,更是一种“分而治之”的思想,合理应用可显著提升支付系统的可维护性、灵活性和可扩展性。