java责任链模式

4 阅读3分钟

责任链模式是一种行为型设计模式,它允许将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求为止。每个处理者都持有对下一个处理者的引用,从而形成一条链。

核心思想

  • 解耦:请求的发送者不需要知道哪个对象会处理请求,处理者之间也互不依赖。
  • 动态组合:可以在运行时灵活地调整链的顺序或成员。
  • 职责分离:每个处理者只关注自己能够处理的请求类型,不能处理的就转发给下一个。

主要角色

  1. 抽象处理器(Handler) :定义处理请求的接口,并持有下一个处理者的引用。
  2. 具体处理器(ConcreteHandler) :实现具体的处理逻辑,决定自己处理还是转发。
  3. 客户端(Client) :创建链,并将请求提交给链的第一个处理者。

代码案例:订单折扣处理链

假设一个电商系统根据订单金额给予不同的折扣:

  • 订单金额 ≥ 1000 元 → 享受 9 折优惠
  • 订单金额 ≥ 500 元 → 享受 95 折优惠
  • 其他情况 → 无折扣

我们可以用责任链模式来依次尝试这些折扣规则,一旦某个规则匹配,就应用折扣并停止传递。

Java 实现

java

// 1. 抽象处理器:折扣处理器
abstract class DiscountHandler {
    protected DiscountHandler next;

    public void setNext(DiscountHandler next) {
        this.next = next;
    }

    // 处理订单折扣,返回最终价格
    public abstract double handleDiscount(double amount);
}

// 2. 具体处理器:高额折扣(满1000打9折)
class HighAmountDiscountHandler extends DiscountHandler {
    @Override
    public double handleDiscount(double amount) {
        if (amount >= 1000) {
            double discounted = amount * 0.9;
            System.out.println("满1000元,享受9折优惠,折后价:" + discounted);
            return discounted;
        } else if (next != null) {
            return next.handleDiscount(amount);
        }
        return amount; // 无后续处理器,原价
    }
}

// 3. 具体处理器:中等折扣(满500打95折)
class MediumAmountDiscountHandler extends DiscountHandler {
    @Override
    public double handleDiscount(double amount) {
        if (amount >= 500) {
            double discounted = amount * 0.95;
            System.out.println("满500元,享受95折优惠,折后价:" + discounted);
            return discounted;
        } else if (next != null) {
            return next.handleDiscount(amount);
        }
        return amount;
    }
}

// 4. 具体处理器:无折扣(兜底)
class NoDiscountHandler extends DiscountHandler {
    @Override
    public double handleDiscount(double amount) {
        System.out.println("无优惠,原价:" + amount);
        return amount;
    }
}

// 5. 客户端
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        // 创建处理器
        HighAmountDiscountHandler highHandler = new HighAmountDiscountHandler();
        MediumAmountDiscountHandler mediumHandler = new MediumAmountDiscountHandler();
        NoDiscountHandler noHandler = new NoDiscountHandler();

        // 构建链:高额 -> 中等 -> 无折扣
        highHandler.setNext(mediumHandler);
        mediumHandler.setNext(noHandler);

        // 测试不同订单金额
        System.out.println("===== 订单金额:1200 =====");
        double price1 = highHandler.handleDiscount(1200);
        System.out.println("最终支付:" + price1 + "\n");

        System.out.println("===== 订单金额:600 =====");
        double price2 = highHandler.handleDiscount(600);
        System.out.println("最终支付:" + price2 + "\n");

        System.out.println("===== 订单金额:300 =====");
        double price3 = highHandler.handleDiscount(300);
        System.out.println("最终支付:" + price3);
    }
}

运行结果

text

===== 订单金额:1200 =====
满1000元,享受9折优惠,折后价:1080.0
最终支付:1080.0

===== 订单金额:600 =====
满500元,享受95折优惠,折后价:570.0
最终支付:570.0

===== 订单金额:300 =====
无优惠,原价:300.0
最终支付:300.0

模式要点

  • 请求沿链传递:每个处理器决定是否处理,如果不处理就调用 next 继续传递。
  • 同步执行:所有处理都在当前线程内顺序完成,没有持久化或异步等待。
  • 灵活扩展:新增折扣规则只需添加新的处理器,并调整链的组装顺序即可,无需修改已有代码。

责任链模式 vs 审批流

正如你之前提到的,经典的 GoF 责任链模式是同步的,所有处理者都在同一个方法调用栈中立即执行。而审批流往往需要持久化、人工参与、异步推进,因此直接套用责任链模式并不合适。但在一些纯规则的、自动化的校验链(如权限校验、数据校验)中,责任链模式依然是非常优雅的选择。