Skip to content

责任链模式 (Chain of Responsibility)

什么是责任链模式?

责任链模式是一种行为型设计模式,它允许你将请求沿着处理者链进行传递。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下一个处理者。

核心思想

  • 解耦发送者和接收者:请求的发送者不需要知道哪个对象会处理请求。
  • 动态组合处理者:可以在运行时动态地添加或修改处理链。
  • 单一职责:每个处理者只负责自己能处理的请求。

实现示例:日志系统

抽象处理器

java
import lombok.Setter;

/**
 * 抽象日志处理器
 * @author yjhu
 */
public abstract class AbstractLogger {
    public static final int INFO = 1;
    public static final int DEBUG = 2;
    public static final int ERROR = 3;

    protected int level;

    // 责任链中的下一个元素
    @Setter
    protected AbstractLogger nextLogger;

    public void logMessage(int level, String message) {
        if (this.level <= level) {
            write(message);
        }
        // 传递给下一个处理器
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    protected abstract void write(String message);
}

具体处理器

java
/**
 * 控制台日志处理器
 * @author yjhu
 */
public class ConsoleLogger extends AbstractLogger {
    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("[Console] " + message);
    }
}

/**
 * 文件日志处理器
 * @author yjhu
 */
public class FileLogger extends AbstractLogger {
    public FileLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("[File] " + message);
    }
}

/**
 * 错误日志处理器(发送邮件通知)
 * @author yjhu
 */
public class ErrorLogger extends AbstractLogger {
    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("[Error - Email Alert] " + message);
    }
}

构建责任链并使用

java
/**
 * 责任链构建器
 * @author yjhu
 */
public class LoggerChainBuilder {
    
    public static AbstractLogger buildChain() {
        // 创建处理器
        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
        AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
        
        // 构建链:Console -> File -> Error
        consoleLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(errorLogger);
        
        return consoleLogger;
    }
}

// 使用示例
public class Demo {
    public static void main(String[] args) {
        AbstractLogger loggerChain = LoggerChainBuilder.buildChain();
        
        System.out.println("=== INFO 级别日志 ===");
        loggerChain.logMessage(AbstractLogger.INFO, "这是一条普通信息");
        
        System.out.println("\n=== DEBUG 级别日志 ===");
        loggerChain.logMessage(AbstractLogger.DEBUG, "这是一条调试信息");
        
        System.out.println("\n=== ERROR 级别日志 ===");
        loggerChain.logMessage(AbstractLogger.ERROR, "这是一条错误信息!");
    }
}

输出结果

=== INFO 级别日志 ===
[Console] 这是一条普通信息

=== DEBUG 级别日志 ===
[Console] 这是一条调试信息
[File] 这是一条调试信息

=== ERROR 级别日志 ===
[Console] 这是一条错误信息!
[File] 这是一条错误信息!
[Error - Email Alert] 这是一条错误信息!

适用场景

  • 审批流程:请假、报销等需要多级审批的场景。
  • 过滤器链:Servlet Filter、Spring Interceptor。
  • 事件处理:GUI 中的事件冒泡机制。
  • 日志记录:不同级别的日志输出到不同目标。

责任链模式的两种变体

变体描述示例
纯责任链请求只能被一个处理者处理,处理后不再传递审批流程
不纯责任链请求可以被多个处理者处理后继续传递日志系统、过滤器链

实际应用

  • Servlet Filter:多个 Filter 组成过滤器链。
  • Spring SecurityFilterChainProxy 管理安全过滤器链。
  • NettyChannelPipeline 中的 ChannelHandler 链。
  • OkHttp:拦截器链(Interceptor Chain)。

优缺点

优点

  • ✅ 降低耦合度,请求发送者和接收者解耦。
  • ✅ 增强灵活性,可动态增加或修改处理者。
  • ✅ 符合单一职责原则,每个处理者只关注自己的逻辑。

缺点

  • ❌ 不能保证请求一定会被处理。
  • ❌ 调试困难,需要跟踪整个链路。
  • ❌ 链过长可能影响性能。