责任链模式

一、责任链模式

  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)

  • 优点

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

    • 日志处理、审批流程、过滤器链、请求校验、数据清洗等。
相关推荐
一抓掉一大把3 分钟前
秒杀-StackExchangeRedisHelper连接单例
java·开发语言·jvm
升鲜宝供应链及收银系统源代码服务4 分钟前
升鲜宝生鲜配送供应链管理系统--- 《多语言商品查询优化方案(Redis + 翻译表 + 模糊匹配)》
java·数据库·redis·bootstrap·供应链系统·生鲜配送·生鲜配送源代码
青山的青衫13 分钟前
【JavaWeb】Tlias后台管理系统
java·web
星释17 分钟前
Rust 练习册 :Minesweeper与二维数组处理
开发语言·后端·rust
蒟蒻的工具人19 分钟前
SSE实时推送订单状态
java·eventsource·sse协议
小蒜学长23 分钟前
springboot基于Java的校园导航微信小程序的设计与实现(代码+数据库+LW)
java·spring boot·后端·微信小程序
王元_SmallA1 小时前
IDEA + Spring Boot 的三种热加载方案
java·后端
小苏兮1 小时前
【把Linux“聊”明白】编译器gcc/g++与调试器gdb/cgdb:从编译原理到高效调试
java·linux·运维·学习·1024程序员节
Java天梯之路1 小时前
04 数据类型转换
java
开发者小天1 小时前
React中的useRef的用法
开发语言·前端·javascript·react.js