责任链模式:把请求像接力棒一样传下去

说实话,责任链模式是我在实际项目中用得最频繁的模式之一。它解决了一个很实际的问题:一个请求来了,到底该由谁处理?

你想想看,审批流程、日志过滤、异常处理,这些场景都有一个共同点——处理者不止一个,而且处理顺序很重要。责任链模式,说白了就是把多个处理者串成一条链,请求沿着链传递,直到有人处理它。

模式的核心思想

责任链模式的定义其实很简单:避免请求发送者与接收者耦合,让多个对象都有机会处理请求。将这些对象连成一条链,沿着链传递请求,直到有对象处理它为止。

我个人习惯把责任链想象成「击鼓传花」——花就是请求,每个人都可以选择处理它,或者传给下一个人。只不过在代码里,这个传递是有明确规则的。

核心角色:
  • 抽象处理者(Handler):定义处理请求的接口,持有下一个处理者的引用
  • 具体处理者(ConcreteHandler):实现处理逻辑,决定是否处理或转发
  • 客户端(Client):组装链并发送请求

一个真实的审批流程

我在做企业级OA系统时,遇到过典型的审批场景。请假申请需要根据天数走不同级别的审批:

  • 3天以内:部门经理审批
  • 3-7天:总监审批
  • 7天以上:总经理审批

如果用if-else写,代码会变得又臭又长。而且每次调整审批规则,都要改核心逻辑。责任链模式正好派上用场。

Java 实现

// 抽象处理者
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 approve(int days);
}

// 具体处理者:部门经理
class Manager extends Approver {
    public Manager(String name) {
        super(name);
    }
    
    @Override
    public void approve(int days) {
        if (days <= 3) {
            System.out.println(name + " 审批通过,请假天数:" + days);
        } else if (nextApprover != null) {
            nextApprover.approve(days);
        }
    }
}

// 具体处理者:总监
class Director extends Approver {
    public Director(String name) {
        super(name);
    }
    
    @Override
    public void approve(int days) {
        if (days <= 7) {
            System.out.println(name + " 审批通过,请假天数:" + days);
        } else if (nextApprover != null) {
            nextApprover.approve(days);
        }
    }
}

// 具体处理者:总经理
class GeneralManager extends Approver {
    public GeneralManager(String name) {
        super(name);
    }
    
    @Override
    public void approve(int days) {
        if (days > 7) {
            System.out.println(name + " 审批通过,请假天数:" + days);
        } else if (nextApprover != null) {
            nextApprover.approve(days);
        }
    }
}

// 客户端组装链
public class Client {
    public static void main(String[] args) {
        Approver manager = new Manager("张经理");
        Approver director = new Director("李总监");
        Approver generalManager = new GeneralManager("王总");
        
        // 组装责任链
        manager.setNextApprover(director);
        director.setNextApprover(generalManager);
        
        // 发送请求
        manager.approve(2);  // 张经理审批
        manager.approve(5);  // 李总监审批
        manager.approve(10); // 王总审批
    }
}

C++ 实现

#include <iostream>
#include <string>
using namespace std;

// 抽象处理者
class Approver {
protected:
    Approver* nextApprover;
    string name;
public:
    Approver(string name) : name(name), nextApprover(nullptr) {}
    void setNextApprover(Approver* next) { nextApprover = next; }
    virtual void approve(int days) = 0;
    virtual ~Approver() {}
};

// 部门经理
class Manager : public Approver {
public:
    Manager(string name) : Approver(name) {}
    void approve(int days) override {
        if (days <= 3) {
            cout << name << " 审批通过,请假天数:" << days << endl;
        } else if (nextApprover != nullptr) {
            nextApprover->approve(days);
        }
    }
};

// 总监
class Director : public Approver {
public:
    Director(string name) : Approver(name) {}
    void approve(int days) override {
        if (days <= 7) {
            cout << name << " 审批通过,请假天数:" << days << endl;
        } else if (nextApprover != nullptr) {
            nextApprover->approve(days);
        }
    }
};

// 总经理
class GeneralManager : public Approver {
public:
    GeneralManager(string name) : Approver(name) {}
    void approve(int days) override {
        if (days > 7) {
            cout << name << " 审批通过,请假天数:" << days << endl;
        } else if (nextApprover != nullptr) {
            nextApprover->approve(days);
        }
    }
};

int main() {
    Approver* manager = new Manager("张经理");
    Approver* director = new Director("李总监");
    Approver* generalManager = new GeneralManager("王总");
    
    manager->setNextApprover(director);
    director->setNextApprover(generalManager);
    
    manager->approve(2);
    manager->approve(5);
    manager->approve(10);
    
    delete manager;
    delete director;
    delete generalManager;
    return 0;
}

责任链的组装方式

链的组装其实就两种方式:

  1. 手动组装:客户端显式调用 setNext() 方法。优点是灵活,缺点是客户端要了解链的结构。
  2. 自动组装:通过配置文件或注解自动构建链。适合链比较固定的场景。

我个人更推荐手动组装,因为代码可读性更强。你一眼就能看出链的顺序。

过滤器链:另一个经典应用

除了审批流程,过滤器链也是责任链模式的典型应用。Java Servlet 中的 FilterChain 就是最好的例子。

我记得有一次做Web项目,需要实现请求的日志记录、权限校验、参数校验。如果用责任链模式,每个过滤器只关心自己的事:

interface Filter {
    void doFilter(Request request, Response response, FilterChain chain);
}

class LogFilter implements Filter {
    public void doFilter(Request request, Response response, FilterChain chain) {
        System.out.println("记录日志:" + request.getUrl());
        chain.doFilter(request, response); // 传给下一个
    }
}

class AuthFilter implements Filter {
    public void doFilter(Request request, Response response, FilterChain chain) {
        if (request.getToken() != null) {
            chain.doFilter(request, response);
        } else {
            System.out.println("未授权,拦截");
        }
    }
}

你看,每个过滤器只做一件事,互不干扰。想加新的过滤器?直接插到链里就行。

责任链模式的结构图

责任链模式结构图 客户端 (Client) 抽象处理者 (Handler) + setNext(Handler) + handleRequest() 具体处理者1 处理条件A,否则转发 具体处理者2 处理条件B,否则转发 具体处理者3 处理条件C,否则转发 next→ next→ 请求流向:客户端 → 处理者1 → 处理者2 → 处理者3

避坑指南

我曾经踩过的坑:
  • 链的循环问题:有一次我不小心把链的最后一个节点的 next 指向了第一个节点,结果请求在链里死循环了。一定要确保链的终点有明确的终止条件。
  • 处理顺序搞反:审批流程中,如果先让总经理处理,再让经理处理,那经理永远没机会。链的顺序决定了处理优先级。
  • 忘记调用 next:在具体处理者中,如果条件不满足,一定要记得调用 nextApprover.handleRequest(),否则链就断了。
我的建议:
  • 每个处理者只做一件事,遵循单一职责原则
  • 链的长度不要超过 5-7 个节点,太长了影响性能
  • 考虑使用建造者模式来组装链,代码会更优雅

什么时候用责任链模式?

场景 说明
审批流程 不同级别审批不同范围的请求
过滤器/拦截器 Web 请求的预处理、后处理
日志框架 不同级别的日志输出到不同目的地
异常处理 不同类型的异常由不同处理器处理

嗯,责任链模式就是这么回事。它不复杂,但用好了能让代码的扩展性提升一大截。下次你遇到「多个处理者按顺序处理请求」的场景,不妨试试它。

公众号:蓝海资料掘金营,微信deep3321