责任链模式详解

117 阅读15分钟

责任链模式详解:从原理到实战

前言

在实际的软件开发中,我们经常会遇到这样的场景:一个请求需要经过多个处理者的处理,但我们不希望请求的发送者与接收者耦合在一起。责任链模式(Chain of Responsibility Pattern)正是为了解决这类问题而诞生的。本文将深入讲解责任链模式的原理、实现方式以及在生产环境中的实际应用。

一、什么是责任链模式

1.1 定义

责任链模式是一种行为型设计模式,它允许你将请求沿着处理者链进行传递,直到其中一个处理者对其进行处理。该模式将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求。

1.2 核心思想

责任链模式的核心思想是:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

1.3 模式结构(ASCII图)

┌─────────────┐
│   Client    │
└──────┬──────┘
       │
       │ request
       ▼
┌─────────────────┐
│    Handler      │◄──────────┐
├─────────────────┤           │
│+ setNext()      │           │
│+ handleRequest()│           │
└────────┬────────┘           │
         │                    │
         │                    │
    ┌────┴────────┐           │
    │             │           │
    ▼             ▼           │
┌─────────┐  ┌─────────┐     │
│Handler1 │  │Handler2 │     │
├─────────┤  ├─────────┤     │
│handle() │  │handle() │     │
└─────────┘  └─────────┘     │
     │                        │
     └────────────────────────┘
          next handler

1.4 角色说明

  • Handler(抽象处理者):定义一个处理请求的接口,包含一个指向下一个处理者的引用
  • ConcreteHandler(具体处理者):实现抽象处理者的处理方法,判断能否处理请求,如果可以则处理,否则转发给下一个处理者
  • Client(客户端):创建并组装责任链,向链上的第一个处理者发送请求

二、责任链模式的实现

2.1 基础实现

首先,我们来看一个简单的责任链模式实现:

/**
 * 抽象处理者
 */
public abstract class Handler {
    protected Handler nextHandler;

    /**
     * 设置下一个处理者
     */
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 处理请求的抽象方法
     */
    public abstract void handleRequest(String request);
}
/**
 * 具体处理者A
 */
public class ConcreteHandlerA extends Handler {

    @Override
    public void handleRequest(String request) {
        if (request.equals("A")) {
            System.out.println("ConcreteHandlerA 处理请求: " + request);
        } else if (nextHandler != null) {
            // 传递给下一个处理者
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理者能够处理该请求");
        }
    }
}
/**
 * 具体处理者B
 */
public class ConcreteHandlerB extends Handler {

    @Override
    public void handleRequest(String request) {
        if (request.equals("B")) {
            System.out.println("ConcreteHandlerB 处理请求: " + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理者能够处理该请求");
        }
    }
}
/**
 * 具体处理者C
 */
public class ConcreteHandlerC extends Handler {

    @Override
    public void handleRequest(String request) {
        if (request.equals("C")) {
            System.out.println("ConcreteHandlerC 处理请求: " + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("没有处理者能够处理该请求");
        }
    }
}
/**
 * 客户端测试
 */
public class Client {
    public static void main(String[] args) {
        // 创建处理者
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        // 构建责任链: A -> B -> C
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 发送请求
        System.out.println("发送请求: A");
        handlerA.handleRequest("A");

        System.out.println("\n发送请求: B");
        handlerA.handleRequest("B");

        System.out.println("\n发送请求: C");
        handlerA.handleRequest("C");

        System.out.println("\n发送请求: D");
        handlerA.handleRequest("D");
    }
}

输出结果:

发送请求: A
ConcreteHandlerA 处理请求: A

发送请求: B
ConcreteHandlerB 处理请求: B

发送请求: C
ConcreteHandlerC 处理请求: C

发送请求: D
没有处理者能够处理该请求

三、生产环境实战案例

3.1 案例一:审批流程系统

在企业管理系统中,不同金额的费用报销需要不同级别的领导审批。这是责任链模式的典型应用场景。

3.1.1 场景分析
审批流程:
┌────────────┐   ┌────────────┐   ┌────────────┐   ┌────────────┐
│  组长审批  │──▶│  经理审批  │──▶│  总监审批  │──▶│  总经理审批│
│  (≤1000)   │   │  (≤5000)   │   │  (≤10000)  │   │   (>10000) │
└────────────┘   └────────────┘   └────────────┘   └────────────┘
3.1.2 代码实现
/**
 * 报销请求类
 */
public class ReimbursementRequest {
    private String employeeName;    // 员工姓名
    private double amount;          // 报销金额
    private String reason;          // 报销理由

    public ReimbursementRequest(String employeeName, double amount, String reason) {
        this.employeeName = employeeName;
        this.amount = amount;
        this.reason = reason;
    }

    public String getEmployeeName() {
        return employeeName;
    }

    public double getAmount() {
        return amount;
    }

    public String getReason() {
        return reason;
    }
}
/**
 * 抽象审批者
 */
public abstract class Approver {
    protected Approver nextApprover;
    protected String name;

    public Approver(String name) {
        this.name = name;
    }

    /**
     * 设置下一个审批者
     */
    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    /**
     * 处理审批请求
     */
    public abstract void processRequest(ReimbursementRequest request);
}
/**
 * 组长审批者(审批金额≤1000)
 */
public class TeamLeader extends Approver {

    public TeamLeader(String name) {
        super(name);
    }

    @Override
    public void processRequest(ReimbursementRequest request) {
        if (request.getAmount() <= 1000) {
            System.out.println("【组长 " + name + " 审批】");
            System.out.println("员工:" + request.getEmployeeName());
            System.out.println("金额:" + request.getAmount() + " 元");
            System.out.println("理由:" + request.getReason());
            System.out.println("审批结果:通过");
            System.out.println("----------------------------------------");
        } else {
            System.out.println("【组长 " + name + "】金额超出权限,转交上级审批...");
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            }
        }
    }
}
/**
 * 经理审批者(审批金额≤5000)
 */
public class Manager extends Approver {

    public Manager(String name) {
        super(name);
    }

    @Override
    public void processRequest(ReimbursementRequest request) {
        if (request.getAmount() <= 5000) {
            System.out.println("【经理 " + name + " 审批】");
            System.out.println("员工:" + request.getEmployeeName());
            System.out.println("金额:" + request.getAmount() + " 元");
            System.out.println("理由:" + request.getReason());
            System.out.println("审批结果:通过");
            System.out.println("----------------------------------------");
        } else {
            System.out.println("【经理 " + name + "】金额超出权限,转交上级审批...");
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            }
        }
    }
}
/**
 * 总监审批者(审批金额≤10000)
 */
public class Director extends Approver {

    public Director(String name) {
        super(name);
    }

    @Override
    public void processRequest(ReimbursementRequest request) {
        if (request.getAmount() <= 10000) {
            System.out.println("【总监 " + name + " 审批】");
            System.out.println("员工:" + request.getEmployeeName());
            System.out.println("金额:" + request.getAmount() + " 元");
            System.out.println("理由:" + request.getReason());
            System.out.println("审批结果:通过");
            System.out.println("----------------------------------------");
        } else {
            System.out.println("【总监 " + name + "】金额超出权限,转交上级审批...");
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            }
        }
    }
}
/**
 * 总经理审批者(审批所有金额)
 */
public class GeneralManager extends Approver {

    public GeneralManager(String name) {
        super(name);
    }

    @Override
    public void processRequest(ReimbursementRequest request) {
        System.out.println("【总经理 " + name + " 审批】");
        System.out.println("员工:" + request.getEmployeeName());
        System.out.println("金额:" + request.getAmount() + " 元");
        System.out.println("理由:" + request.getReason());

        if (request.getAmount() <= 50000) {
            System.out.println("审批结果:通过");
        } else {
            System.out.println("审批结果:金额过大,需要董事会审批");
        }
        System.out.println("----------------------------------------");
    }
}
/**
 * 测试客户端
 */
public class ReimbursementTest {
    public static void main(String[] args) {
        // 创建审批者
        Approver teamLeader = new TeamLeader("张三");
        Approver manager = new Manager("李四");
        Approver director = new Director("王五");
        Approver generalManager = new GeneralManager("赵六");

        // 构建责任链
        teamLeader.setNextApprover(manager);
        manager.setNextApprover(director);
        director.setNextApprover(generalManager);

        // 测试不同金额的报销请求
        ReimbursementRequest request1 = new ReimbursementRequest(
            "小明", 800, "购买办公用品"
        );
        teamLeader.processRequest(request1);

        ReimbursementRequest request2 = new ReimbursementRequest(
            "小红", 3500, "参加技术培训"
        );
        teamLeader.processRequest(request2);

        ReimbursementRequest request3 = new ReimbursementRequest(
            "小刚", 8000, "采购服务器设备"
        );
        teamLeader.processRequest(request3);

        ReimbursementRequest request4 = new ReimbursementRequest(
            "小李", 25000, "市场推广活动"
        );
        teamLeader.processRequest(request4);
    }
}

输出结果:

【组长 张三 审批】
员工:小明
金额:800.0 元
理由:购买办公用品
审批结果:通过
----------------------------------------
【组长 张三】金额超出权限,转交上级审批...
【经理 李四 审批】
员工:小红
金额:3500.0 元
理由:参加技术培训
审批结果:通过
----------------------------------------
【组长 张三】金额超出权限,转交上级审批...
【经理 李四】金额超出权限,转交上级审批...
【总监 王五 审批】
员工:小刚
金额:8000.0 元
理由:采购服务器设备
审批结果:通过
----------------------------------------
【组长 张三】金额超出权限,转交上级审批...
【经理 李四】金额超出权限,转交上级审批...
【总监 王五】金额超出权限,转交上级审批...
【总经理 赵六 审批】
员工:小李
金额:25000.0 元
理由:市场推广活动
审批结果:通过
----------------------------------------

3.2 案例二:日志处理系统

在日志系统中,不同级别的日志需要不同的处理方式,这也是责任链模式的经典应用。

3.2.1 日志级别结构
日志处理链:
┌─────────┐   ┌─────────┐   ┌─────────┐
│  INFO   │──▶│ WARNING │──▶│  ERROR  │
│ Handler │   │ Handler │   │ Handler │
└─────────┘   └─────────┘   └─────────┘
3.2.2 代码实现
/**
 * 日志级别枚举
 */
public enum LogLevel {
    INFO(1, "INFO"),
    WARNING(2, "WARNING"),
    ERROR(3, "ERROR");

    private int level;
    private String name;

    LogLevel(int level, String name) {
        this.level = level;
        this.name = name;
    }

    public int getLevel() {
        return level;
    }

    public String getName() {
        return name;
    }
}
/**
 * 抽象日志处理器
 */
public abstract class LogHandler {
    protected LogLevel level;
    protected LogHandler nextHandler;

    public void setNextHandler(LogHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public void logMessage(LogLevel level, String message) {
        if (this.level.getLevel() <= level.getLevel()) {
            write(message);
        }
        if (nextHandler != null) {
            nextHandler.logMessage(level, message);
        }
    }

    protected abstract void write(String message);
}
/**
 * 控制台日志处理器(处理INFO及以上级别)
 */
public class ConsoleLogger extends LogHandler {

    public ConsoleLogger() {
        this.level = LogLevel.INFO;
    }

    @Override
    protected void write(String message) {
        System.out.println("[CONSOLE] " + message);
    }
}
/**
 * 文件日志处理器(处理WARNING及以上级别)
 */
public class FileLogger extends LogHandler {

    public FileLogger() {
        this.level = LogLevel.WARNING;
    }

    @Override
    protected void write(String message) {
        System.out.println("[FILE] 写入日志文件: " + message);
    }
}
/**
 * 错误日志处理器(处理ERROR级别)
 */
public class ErrorLogger extends LogHandler {

    public ErrorLogger() {
        this.level = LogLevel.ERROR;
    }

    @Override
    protected void write(String message) {
        System.out.println("[ERROR] 发送告警邮件: " + message);
    }
}
/**
 * 日志系统测试
 */
public class LoggerTest {

    private static LogHandler getChainOfLoggers() {
        LogHandler consoleLogger = new ConsoleLogger();
        LogHandler fileLogger = new FileLogger();
        LogHandler errorLogger = new ErrorLogger();

        // 构建责任链
        consoleLogger.setNextHandler(fileLogger);
        fileLogger.setNextHandler(errorLogger);

        return consoleLogger;
    }

    public static void main(String[] args) {
        LogHandler loggerChain = getChainOfLoggers();

        System.out.println("===== 记录INFO日志 =====");
        loggerChain.logMessage(LogLevel.INFO, "这是一条普通信息");

        System.out.println("\n===== 记录WARNING日志 =====");
        loggerChain.logMessage(LogLevel.WARNING, "这是一条警告信息");

        System.out.println("\n===== 记录ERROR日志 =====");
        loggerChain.logMessage(LogLevel.ERROR, "这是一条错误信息");
    }
}

输出结果:

===== 记录INFO日志 =====
[CONSOLE] 这是一条普通信息

===== 记录WARNING日志 =====
[CONSOLE] 这是一条警告信息
[FILE] 写入日志文件: 这是一条警告信息

===== 记录ERROR日志 =====
[CONSOLE] 这是一条错误信息
[FILE] 写入日志文件: 这是一条错误信息
[ERROR] 发送告警邮件: 这是一条错误信息

3.3 案例三:敏感词过滤系统

在内容审核系统中,我们需要对用户发布的内容进行多层过滤,这也是责任链模式的实际应用。

3.3.1 过滤链结构
内容过滤链:
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│ 敏感词过滤  │──▶│  HTML过滤   │──▶│  SQL注入过滤 │
└─────────────┘   └─────────────┘   └─────────────┘
3.3.2 代码实现
/**
 * 内容请求类
 */
public class ContentRequest {
    private String content;
    private boolean passed;
    private String rejectReason;

    public ContentRequest(String content) {
        this.content = content;
        this.passed = true;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public boolean isPassed() {
        return passed;
    }

    public void reject(String reason) {
        this.passed = false;
        this.rejectReason = reason;
    }

    public String getRejectReason() {
        return rejectReason;
    }
}
/**
 * 抽象内容过滤器
 */
public abstract class ContentFilter {
    protected ContentFilter nextFilter;

    public void setNextFilter(ContentFilter nextFilter) {
        this.nextFilter = nextFilter;
    }

    public void filter(ContentRequest request) {
        // 执行当前过滤器的过滤逻辑
        doFilter(request);

        // 如果通过了当前过滤器,且有下一个过滤器,则继续传递
        if (request.isPassed() && nextFilter != null) {
            nextFilter.filter(request);
        }
    }

    protected abstract void doFilter(ContentRequest request);
}
/**
 * 敏感词过滤器
 */
public class SensitiveWordFilter extends ContentFilter {

    private static final String[] SENSITIVE_WORDS = {"暴力", "色情", "赌博"};

    @Override
    protected void doFilter(ContentRequest request) {
        String content = request.getContent();
        System.out.println("【敏感词过滤器】正在检查内容...");

        for (String word : SENSITIVE_WORDS) {
            if (content.contains(word)) {
                request.reject("内容包含敏感词:" + word);
                System.out.println("过滤结果:不通过 - " + request.getRejectReason());
                return;
            }
        }
        System.out.println("过滤结果:通过");
    }
}
/**
 * HTML标签过滤器
 */
public class HtmlTagFilter extends ContentFilter {

    @Override
    protected void doFilter(ContentRequest request) {
        String content = request.getContent();
        System.out.println("【HTML标签过滤器】正在检查内容...");

        if (content.contains("<script>") || content.contains("</script>")) {
            request.reject("内容包含非法HTML标签");
            System.out.println("过滤结果:不通过 - " + request.getRejectReason());
            return;
        }

        // 过滤HTML标签
        String filtered = content.replaceAll("<[^>]*>", "");
        if (!filtered.equals(content)) {
            System.out.println("过滤结果:已清理HTML标签");
            request.setContent(filtered);
        } else {
            System.out.println("过滤结果:通过");
        }
    }
}
/**
 * SQL注入过滤器
 */
public class SqlInjectionFilter extends ContentFilter {

    private static final String[] SQL_KEYWORDS = {
        "select", "insert", "update", "delete", "drop", "union"
    };

    @Override
    protected void doFilter(ContentRequest request) {
        String content = request.getContent().toLowerCase();
        System.out.println("【SQL注入过滤器】正在检查内容...");

        for (String keyword : SQL_KEYWORDS) {
            if (content.contains(keyword)) {
                request.reject("内容疑似包含SQL注入攻击");
                System.out.println("过滤结果:不通过 - " + request.getRejectReason());
                return;
            }
        }
        System.out.println("过滤结果:通过");
    }
}
/**
 * 内容过滤系统测试
 */
public class ContentFilterTest {

    private static ContentFilter buildFilterChain() {
        ContentFilter sensitiveWordFilter = new SensitiveWordFilter();
        ContentFilter htmlTagFilter = new HtmlTagFilter();
        ContentFilter sqlInjectionFilter = new SqlInjectionFilter();

        // 构建过滤链
        sensitiveWordFilter.setNextFilter(htmlTagFilter);
        htmlTagFilter.setNextFilter(sqlInjectionFilter);

        return sensitiveWordFilter;
    }

    public static void main(String[] args) {
        ContentFilter filterChain = buildFilterChain();

        // 测试案例1:正常内容
        System.out.println("========== 测试案例1:正常内容 ==========");
        ContentRequest request1 = new ContentRequest("这是一条正常的评论内容");
        filterChain.filter(request1);
        System.out.println("最终结果:" + (request1.isPassed() ? "发布成功" : "发布失败"));
        System.out.println();

        // 测试案例2:包含敏感词
        System.out.println("========== 测试案例2:包含敏感词 ==========");
        ContentRequest request2 = new ContentRequest("这条内容包含暴力信息");
        filterChain.filter(request2);
        System.out.println("最终结果:" + (request2.isPassed() ? "发布成功" : "发布失败"));
        System.out.println();

        // 测试案例3:包含HTML标签
        System.out.println("========== 测试案例3:包含HTML标签 ==========");
        ContentRequest request3 = new ContentRequest("这是<b>加粗</b>的内容");
        filterChain.filter(request3);
        System.out.println("最终结果:" + (request3.isPassed() ? "发布成功" : "发布失败"));
        if (request3.isPassed()) {
            System.out.println("处理后的内容:" + request3.getContent());
        }
        System.out.println();

        // 测试案例4:包含SQL注入
        System.out.println("========== 测试案例4:疑似SQL注入 ==========");
        ContentRequest request4 = new ContentRequest("'; DROP TABLE users; --");
        filterChain.filter(request4);
        System.out.println("最终结果:" + (request4.isPassed() ? "发布成功" : "发布失败"));
    }
}

输出结果:

========== 测试案例1:正常内容 ==========
【敏感词过滤器】正在检查内容...
过滤结果:通过
【HTML标签过滤器】正在检查内容...
过滤结果:通过
【SQL注入过滤器】正在检查内容...
过滤结果:通过
最终结果:发布成功

========== 测试案例2:包含敏感词 ==========
【敏感词过滤器】正在检查内容...
过滤结果:不通过 - 内容包含敏感词:暴力
最终结果:发布失败

========== 测试案例3:包含HTML标签 ==========
【敏感词过滤器】正在检查内容...
过滤结果:通过
【HTML标签过滤器】正在检查内容...
过滤结果:已清理HTML标签
【SQL注入过滤器】正在检查内容...
过滤结果:通过
最终结果:发布成功
处理后的内容:这是加粗的内容

========== 测试案例4:疑似SQL注入 ==========
【敏感词过滤器】正在检查内容...
过滤结果:通过
【HTML标签过滤器】正在检查内容...
过滤结果:通过
【SQL注入过滤器】正在检查内容...
过滤结果:不通过 - 内容疑似包含SQL注入攻击
最终结果:发布失败

四、责任链模式的优化

4.1 使用建造者模式优化责任链构建

为了使责任链的构建更加优雅,我们可以结合建造者模式:

/**
 * 责任链建造者
 */
public class FilterChainBuilder {
    private ContentFilter head;
    private ContentFilter tail;

    public FilterChainBuilder addFilter(ContentFilter filter) {
        if (head == null) {
            head = filter;
            tail = filter;
        } else {
            tail.setNextFilter(filter);
            tail = filter;
        }
        return this;
    }

    public ContentFilter build() {
        return head;
    }
}

使用示例:

ContentFilter filterChain = new FilterChainBuilder()
    .addFilter(new SensitiveWordFilter())
    .addFilter(new HtmlTagFilter())
    .addFilter(new SqlInjectionFilter())
    .build();

4.2 Spring中的责任链模式实现

在Spring框架中,我们可以利用依赖注入来更优雅地实现责任链模式:

/**
 * 过滤器接口
 */
public interface Filter {
    int getOrder();
    void doFilter(ContentRequest request);
}
/**
 * 过滤器管理器
 */
@Component
public class FilterChainManager {

    @Autowired
    private List<Filter> filters;

    @PostConstruct
    public void init() {
        // 按order排序
        filters.sort(Comparator.comparingInt(Filter::getOrder));
    }

    public void executeFilters(ContentRequest request) {
        for (Filter filter : filters) {
            filter.doFilter(request);
            if (!request.isPassed()) {
                break;
            }
        }
    }
}
/**
 * 具体过滤器实现
 */
@Component
public class SensitiveWordFilterImpl implements Filter {

    @Override
    public int getOrder() {
        return 1;
    }

    @Override
    public void doFilter(ContentRequest request) {
        // 过滤逻辑
    }
}

五、责任链模式的优缺点

5.1 优点

  1. 降低耦合度:请求的发送者和接收者解耦,发送者不需要知道是哪个处理者最终处理了请求

  2. 增强灵活性:可以动态地添加、删除或调整处理者的顺序,而不影响其他代码

  3. 符合单一职责原则:每个处理者只需关注自己能处理的请求

  4. 符合开闭原则:增加新的处理者时,不需要修改原有代码

5.2 缺点

  1. 性能问题:如果责任链过长,会影响性能,因为请求需要遍历整个链

  2. 调试困难:由于请求是动态分配的,调试时不容易观察运行时的特征

  3. 可能无法处理:如果没有正确配置责任链,可能导致请求无法被处理

  4. 建链麻烦:需要在客户端手动建立责任链,增加了客户端的复杂度

六、责任链模式的应用场景

6.1 适用场景

  1. 多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定

  2. 需要动态指定处理一组对象的处理顺序

  3. 不希望明确指定接收者的情况下,向多个对象中的一个提交请求

  4. 可处理一个请求的对象集合需要被动态指定

6.2 常见应用

  1. 审批流程:OA系统中的请假、报销等审批
  2. 日志系统:不同级别的日志处理
  3. 过滤器:Servlet的Filter链、Spring的拦截器
  4. 异常处理:多级异常捕获和处理
  5. 权限验证:多层权限校验
  6. 事件处理:GUI系统中的事件冒泡机制

七、框架中的责任链模式

7.1 Java Servlet Filter

public class EncodingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                        FilterChain chain) throws IOException, ServletException {
        // 前置处理
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        // 传递给下一个过滤器
        chain.doFilter(request, response);

        // 后置处理
        System.out.println("EncodingFilter 后置处理");
    }
}

7.2 Spring Interceptor

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler) throws Exception {
        // 前置处理
        String token = request.getHeader("token");
        if (token == null) {
            response.sendError(401, "未登录");
            return false; // 中断责任链
        }
        return true; // 继续传递
    }

    @Override
    public void postHandle(HttpServletRequest request,
                          HttpServletResponse response,
                          Object handler,
                          ModelAndView modelAndView) throws Exception {
        // 后置处理
    }
}

7.3 Netty Pipeline

ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new CustomHandler());

八、责任链模式 vs 其他模式

8.1 责任链模式 vs 装饰者模式

对比维度责任链模式装饰者模式
目的将请求传递给链上的某个对象处理动态地给对象添加额外职责
处理方式只有一个对象处理请求(或都处理)所有装饰者都会处理
顺序按链的顺序传递按装饰的顺序叠加

8.2 责任链模式 vs 策略模式

对比维度责任链模式策略模式
对象关系链式结构,对象之间有先后顺序平行关系,对象之间相互独立
选择方式动态决定由哪个对象处理由客户端选择具体策略
处理数量可能有多个对象处理只有一个策略对象处理

九、最佳实践

9.1 设计建议

  1. 合理控制链的长度:避免责任链过长影响性能
  2. 提供默认处理:在链的末尾提供默认处理者,避免请求无法处理
  3. 避免循环引用:注意不要让责任链形成环
  4. 考虑缓存:对于频繁执行的责任链,可以考虑缓存结果

9.2 代码规范

/**
 * 推荐的责任链处理者模板
 */
public abstract class AbstractHandler {
    protected AbstractHandler nextHandler;

    public AbstractHandler setNext(AbstractHandler handler) {
        this.nextHandler = handler;
        return handler; // 返回下一个处理者,支持链式调用
    }

    public final void handle(Request request) {
        // 模板方法
        if (canHandle(request)) {
            doHandle(request);
        }

        if (nextHandler != null && shouldContinue(request)) {
            nextHandler.handle(request);
        }
    }

    protected abstract boolean canHandle(Request request);
    protected abstract void doHandle(Request request);
    protected boolean shouldContinue(Request request) {
        return true; // 默认继续传递
    }
}

十、总结

责任链模式是一种非常实用的设计模式,它通过将请求的发送者和接收者解耦,使系统更加灵活和可扩展。在实际开发中,责任链模式被广泛应用于各种场景,如审批流程、日志处理、过滤器链等。

关键要点:

  1. 责任链模式将请求沿着处理者链传递,直到某个处理者处理它为止
  2. 核心优势是降低耦合度,增强系统的灵活性和可扩展性
  3. 需要注意控制责任链的长度,避免性能问题
  4. 在实际应用中,可以结合建造者模式、Spring框架等进行优化
  5. 许多主流框架(如Servlet、Spring、Netty)都使用了责任链模式

掌握责任链模式,不仅能帮助我们编写更优雅的代码,还能让我们更好地理解和使用各种主流框架。希望本文能帮助你深入理解责任链模式,并在实际项目中灵活运用。