责任链模式

一、责任链模式

  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)

  • 优点

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

    • 日志处理、审批流程、过滤器链、请求校验、数据清洗等。
相关推荐
whm277716 小时前
Visual Basic 参数传送-形参与实参
开发语言·visual studio
9号达人16 小时前
if-else 优化的折中思考:不是消灭分支,而是控制风险
java·后端·面试
共享家952716 小时前
QT-常用控件(多元素控件)
开发语言·前端·qt
幸运小圣16 小时前
Iterator迭代器 【ES6】
开发语言·javascript·es6
葱头的故事16 小时前
将传给后端的数据转换为以formData的类型传递
开发语言·前端·javascript
不知道累,只知道类16 小时前
Java 在AWS上使用SDK凭证获取顺序
java·aws
咖啡Beans17 小时前
SpringBoot2.7集成Swagger3.0
java·swagger
一念&17 小时前
每日一个C语言知识:C 数组
c语言·开发语言·算法
小年糕是糕手17 小时前
【数据结构】单链表“0”基础知识讲解 + 实战演练
c语言·开发语言·数据结构·c++·学习·算法·链表
聪明的笨猪猪17 小时前
Java JVM “垃圾回收(GC)”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试