设计模式-责任链模式

一、简介

责任链模式 (Chain of Responsibility Pattern)是一种行为型设计模式,用于将请求的发送者与接收者解耦,使多个处理对象都有机会处理该请求。这些处理对象通过形成一条链式结构依次处理请求,直到某个对象能够完成处理或处理链结束。

责任链模式的核心思想是:将多个可能处理请求的对象连接成一条链,沿着链传递请求,直至某个处理对象处理它或链的末端。

应用场景

  • 请求需要被多个对象处理:比如击鼓传花、事件冒泡机制、权限校验、日志记录等。
  • 请求的处理逻辑需要灵活扩展:可以动态地增加或移除处理器。
  • 避免请求的发送者和接收者之间的强耦合:发送者无需指定接收者,接收者可以灵活变化。

二、优缺点

优点
  1. 请求解耦:请求发送者和处理者解耦,降低代码耦合度。
  2. 灵活性高:可以动态组合和扩展处理链。
  3. 单一职责:每个处理器只关注自身的逻辑,符合开闭原则。
缺点
  1. 性能问题:如果链很长,可能会影响性能。
  2. 调试困难:请求的最终处理者不容易追踪,可能需要额外的日志记录。
  3. 请求未被处理:不能保证请求一定会被链中的某个处理者接收。

三、实际应用

场景

需求:针对不同用户群体设计多种校验规则:

  • A群体:仅需校验手机验证码。
  • B群体:需同时校验手机验证码和用户年龄。

要求根据用户群体的不同动态应用对应的校验规则,实现灵活性和扩展性。

代码实现:

步骤一:构造handler

java 复制代码
public abstract class AbstractCheckHandler {

    public abstract void handler(CheckVO checkVO);

    public abstract int getCode();
}

步骤二 实现handler 进行不同的规则校验

java 复制代码
public class PhoneCheckHandler extends AbstractCheckHandler {

    @Override
    public void handler(CheckVO checkVO) {
        if (checkVO.getVerificationCode() == null) {
            throw new RuntimeException("验证码不能为空!!");
        }
        if (!Integer.valueOf("0000").equals(checkVO.getVerificationCode())) {
            throw new RuntimeException("验证码错误!!");
        }
    }

    @Override
    public int getCode() {
        return 1;
    }
}
java 复制代码
public class UserCheckHandler extends AbstractCheckHandler {

    private static Integer LEGAL_AGE = 18;

    @Override
    public void handler(CheckVO checkVO) {
        if (checkVO.getUserId() == null) {
            throw new RuntimeException("用户不能为空");
        }
        if (LEGAL_AGE >= checkVO.getAge()) {
            throw new RuntimeException("用户未满十八岁");
        }
    }

    @Override
    public int getCode() {
        return 0;
    }
}

步骤三 指定链路的传递方式 通过codeList进行控制

java 复制代码
public class CheckHandlerExecution {

    private final List<AbstractCheckHandler> handlers;

    public CheckHandlerExecution(){
        this.handlers = new ArrayList<>();
        this.handlers.add(new UserCheckHandler());
        this.handlers.add(new PhoneCheckHandler());
    }

    public CheckHandlerExecution(List<AbstractCheckHandler> handlers) {
        this.handlers = handlers;
    }

    public void handle(List<Integer> codeList, CheckVO checkVO) {
        for (AbstractCheckHandler handler : handlers) {
            int code = handler.getCode();
            if (codeList.contains(code)) {
                handler.handler(checkVO);
            }
        }
    }
}

步骤四 代码验证 针对不同用户群体通过list中的code进行控制校验 ,list可以配置在数据库中实现手动配置,从而进行动态校验

java 复制代码
public class CorCheckTest {

    public static void main(String[] args) {
        CheckVO vo = new CheckVO();
        vo.setAge(16);
        vo.setUserId(123456);
        vo.setAreaCode("+86");
        vo.setVerificationCode(0000);

        CheckHandlerExecution execution = new CheckHandlerExecution();
        // 只执行手机号验证
        execution.handle(Arrays.asList(1), vo);
        // 同时执行手机号和用户年龄验证
        execution.handle(Arrays.asList(0, 1), vo);
    }
}
相关推荐
青云交12 分钟前
Java 大视界 -- Java 大数据在智能家居场景联动与用户行为模式挖掘中的应用
java·大数据·智能家居·边缘计算·户型适配·行为挖掘·场景联动
AAA修煤气灶刘哥19 分钟前
ES 高级玩法大揭秘:从算分骚操作到深度分页踩坑,后端 er 速进!
java·后端·elasticsearch
江团1io023 分钟前
深入解析MVCC:多版本并发控制的原理与实现
java·经验分享·mysql
树码小子31 分钟前
Java网络编程:(socket API编程:UDP协议的 socket API -- 回显程序的服务器端程序的编写)
java·网络·udp
君宝36 分钟前
Linux ALSA架构:PCM_OPEN流程 (二)
java·linux·c++
云深麋鹿1 小时前
数据链路层总结
java·网络
fire-flyer1 小时前
响应式客户端 WebClient详解
java·spring·reactor
北执南念1 小时前
基于 Spring 的策略模式框架,用于根据不同的类的标识获取对应的处理器实例
java·spring·策略模式
王道长服务器 | 亚马逊云1 小时前
一个迁移案例:从传统 IDC 到 AWS 的真实对比
java·spring boot·git·云计算·github·dubbo·aws
华仔啊1 小时前
为什么 keySet() 是 HashMap 遍历的雷区?90% 的人踩过
java·后端