责任链模式

一、责任链模式

  1. 背景:为了避免请求发送者与多个请求处理者耦合在一起
    做法:将所有请求的处理者通过【前一对象记住其下一个对象的引用】而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
  2. 比较常见的SpringMVC中的拦截器,Web开发中的filter过滤器。
  3. 职责链模式主要包含以下角色:
    • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
    • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
    • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
  4. (1) "纯"职责链(Pure Chain of Responsibility)每个节点要么处理请求,要么把请求传给下一个节点;一旦某个节点处理了请求,就不会继续往下传递;常用于审批流、过滤器链、拦截器机制等。
    (2) "不纯"职责链(Impure Chain of Responsibility)每个节点都可以对请求进行部分处理;即使某节点处理了,也可以继续传递给下一个节点。

二、订单信息类(OrderInfo.java)

java 复制代码
package com.itheima.designpattern.chain;

import java.math.BigDecimal;

/**
 * 订单信息类(OrderInfo)
 * --------------------------
 * 封装订单的基本数据结构。
 * 在责任链中,会被依次传递并加工。
 */
public class OrderInfo {

    /**
     * 商品ID
     */
    private String productId;

    /**
     * 用户ID
     */
    private String userId;

    /**
     * 订单金额
     */
    private BigDecimal amount;

    // Getter / Setter 方法
    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }
}

三、抽象处理者(Handler.java)

java 复制代码
package com.itheima.designpattern.chain;

/**
 * 抽象处理者(Handler)
 * -------------------------
 * 职责链模式的核心抽象类,定义了:
 * 1. 每个处理者都持有下一个处理者(handler)的引用;
 * 2. 定义了抽象的处理方法 process(OrderInfo order),由子类具体实现;
 * 3. 提供 setNext() 方法用于设置链条中的下一个处理节点。
 */
public abstract class Handler {

    /**
     * 下一个处理者(链条中的下一个节点)
     */
    protected Handler handler;

    /**
     * 设置下一个处理者
     *
     * @param handler 下一个责任链节点
     */
    public void setNext(Handler handler) {
        this.handler = handler;
    }

    /**
     * 抽象处理方法(由子类实现具体业务逻辑)
     *
     * @param order 订单对象
     */
    public abstract boolean process(OrderInfo order);
}


四、具体处理者(Concrete Handlers)

1️⃣ 校验订单信息(OrderValidation.java)

java 复制代码
package com.itheima.designpattern.chain;

/**
 * 具体处理者:订单校验
 * -------------------------
 * 负责校验订单的基本信息是否完整、有效。
 * 如果校验通过,则将订单传递给下一个处理者。
 */
public class OrderValidation extends Handler {

    @Override
    public void process(OrderInfo order) {
        System.out.println("【步骤1】校验订单基本信息");
        // 模拟校验逻辑(例如检查 productId、userId 是否为空)
        // ...

        // 模拟校验失败情况
        if (order.getProductId() == null || order.getUserId() == null) {
            System.out.println("❌ 校验失败:订单信息不完整,流程中止!");
            return false; // 不再传递
        }

        // 校验成功,传递下一个节点
        return handler != null && handler.process(order);
    }
}

2️⃣ 补充订单信息(OrderFill.java)

java 复制代码
package com.itheima.designpattern.chain;

/**
 * 具体处理者:补充订单信息
 * -------------------------
 * 负责在订单校验通过后,补全缺失的订单信息。
 * 例如填充默认字段、计算下单时间等。
 */
public class OrderFill extends Handler {

    @Override
    public void process(OrderInfo order) {
        System.out.println("【步骤2】补充订单信息");
        // 模拟补充逻辑
        // order.setCreateTime(LocalDateTime.now());
        // ...

       // 继续传递
        return handler != null && handler.process(order);
    }
}

3️⃣ 计算订单金额(OrderAmountCalculate.java)

java 复制代码
package com.itheima.designpattern.chain;

/**
 * 具体处理者:计算订单金额
 * -------------------------
 * 负责订单金额的计算,包括:
 *  - 优惠券抵扣
 *  - 会员折扣
 *  - 活动满减等逻辑
 */
public class OrderAmountCalculate extends Handler {

    @Override
    public void process(OrderInfo order) {
        System.out.println("【步骤3】计算金额 - 优惠券、VIP折扣、活动减免");
        // 模拟金额计算逻辑
        // order.setAmount(order.getAmount().multiply(new BigDecimal("0.9")));
        // ...

       // 模拟异常情况
        if (order.getAmount() == null || order.getAmount().doubleValue() <= 0) {
            System.out.println("❌ 金额异常,终止处理!");
            return false; // 中断链条
        }

        // 正常继续
        return handler != null && handler.process(order);
    }
}

4️⃣ 订单入库(OrderCreate.java)

java 复制代码
package com.itheima.designpattern.chain;

/**
 * 具体处理者:订单入库
 * -------------------------
 * 作为责任链的最后一个节点。
 * 负责将订单数据写入数据库或存储系统。
 */
public class OrderCreate extends Handler {

    @Override
    public void process(OrderInfo order) {
        System.out.println("【步骤4】订单入库(持久化保存)");
        // 模拟入库逻辑
        // orderRepository.save(order);
        // 最后一个节点,没有下一个
        return true;
    }
}

五、客户端调用类(Application.java)

java 复制代码
package com.itheima.designpattern.chain;

/**
 * 客户端类
 * -------------------------
 * 演示如何组装并执行责任链。
 *
 * 职责链执行顺序:
 *   OrderValidation → OrderFill → OrderAmountCalculate → OrderCreate
 *
 * 当调用第一个节点的 process() 时,整个链条将依次执行。
 */
public class Application {

    public static void main(String[] args) {
        // 创建各个处理节点
        Handler orderValidation = new OrderValidation();         // 校验订单
        Handler orderFill = new OrderFill();                     // 补充信息
        Handler orderAmountCalculate = new OrderAmountCalculate(); // 金额计算
        Handler orderCreate = new OrderCreate();                 // 入库

        // 构建责任链路
        orderValidation.setNext(orderFill);
        orderFill.setNext(orderAmountCalculate);
        orderAmountCalculate.setNext(orderCreate);

        // 模拟订单对象
        OrderInfo order = new OrderInfo();
        order.setProductId("P1001");
        order.setUserId("U2025");
        order.setAmount(new java.math.BigDecimal("299.00"));

        // 开始执行责任链
        System.out.println("=== 开始订单处理流程 ===");
        orderValidation.process(order);
        System.out.println("=== 订单处理完成 ===");
    }
}

💡 总结:

  • 设计模式类型:职责链模式(Chain of Responsibility Pattern)

  • 优点

    • 请求与处理解耦,灵活添加或移除节点;
    • 每个节点只关注自己的职责;
    • 节点顺序可动态调整。
  • 应用场景

    • 日志处理、审批流程、过滤器链、请求校验、数据清洗等。
相关推荐
雨中飘荡的记忆38 分钟前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
心之语歌3 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
华仔啊4 小时前
Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅
java·后端
ray_liang4 小时前
用六边形架构与整洁架构对比是伪命题?
java·架构
Ray Liang6 小时前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解6 小时前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
SimonKing10 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean10 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven9711 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林55121 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java