设计模式-责任链设计模式

news2024/12/18 14:45:38

核心思想

  • 客户端发出一个请求,链上的对象都有机会来处理这一请求,而客户端不需要知道谁是具体的处理对象
  • 让多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条调用链,并沿着这条链传递该请求,直到有一个对象处理它才终止
  • 两个核心行为:一是处理请求,二是将请求传递到下一节点

场景使用

  • 在请求处理者不明确的情况下向多个对象中的一个提交请求
  • 如果有多个对象可以处理同一个请求,但是具体由哪个对象处理是由运行时刻动态决定的,这种对象就可以使用职责链模式
  • SpringBoot里面的拦截器、过滤器链

在这里插入图片描述

优缺点

优点

  • 客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递
  • 通过改变链内的调动它们的次序,允许动态地新增或者删除处理类,比较很方便维护
  • 增强了系统的可扩展性,可以根据需要增加新的请求处理类,满足开闭原则
  • 每个类只需要处理自己该处理的工作,明确各类的责任范围,满足单一职责原则

缺点

  • 处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完
  • 不能保证请求一定被接收
  • 如果链路比较长,系统性能将受到一定影响,而且在进行代码调试时不太方便

代码示例

业务示意图

在这里插入图片描述

配置 Request 类


public class Request {

    /**
     * 类别
     */
    private String requestType;

    /**
     * 金额
     */
    private int money;

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}

请求类型枚举 RequestType

public enum RequestType {

    /**
     * 转账
     */
    TRANSFER,

    /**
     * 提现
     */
    CASH_OUT;
}

风控抽象类 RiskControlManager


public abstract class RiskControlManager {


    protected  String name;

    /**
     * 更严格的风控策略
     */
    protected RiskControlManager superior;

    public RiskControlManager(String name){
        this.name = name;
    }


    /**
     * 设置更严格的风控策略
     * @param superior
     */
    public void setSuperior(RiskControlManager superior){
        this.superior = superior;
    }


    /**
     * 处理请求
     * @param request
     */
    public abstract void handlerRequest(Request request);

}

初级风控 FirstRiskControlManager


public class FirstRiskControlManager extends RiskControlManager {

    public FirstRiskControlManager(String name) {
        super(name);
    }

    /**
     *  1000元以内可以直接处理
     * @param request
     */
    @Override
    public void handlerRequest(Request request) {

        if(RequestType.valueOf(request.getRequestType())!=null && request.getMoney()<=1000){

            System.out.println("普通操作,输入支付密码即可");

            System.out.println(name+":"+request.getRequestType() + ", 金额:"+request.getMoney() +" 处理完成");

        }else {

            //下个节点进行处理
            if(superior!=null){
                superior.handlerRequest(request);
            }
        }

    }
}

中级风控


public class SecondRiskControlManager extends RiskControlManager {

    public SecondRiskControlManager(String name) {
        super(name);
    }

    /**
     * 处理 1千到1万之间
     * @param request
     */
    @Override
    public void handlerRequest(Request request) {
        if(RequestType.valueOf(request.getRequestType())!=null && request.getMoney()>1000 && request.getMoney()<10000){

            System.out.println("稍大额操作,输入支付密码+短信验证码即可");

            System.out.println(name+":"+request.getRequestType() + ", 金额:"+request.getMoney() +" 处理完成");

        }else {

            //下个节点进行处理
            if(superior!=null){
                superior.handlerRequest(request);
            }
        }
    }
}

高级风控 ThirdRiskControlManager


public class ThirdRiskControlManager extends RiskControlManager {

    public ThirdRiskControlManager(String name) {
        super(name);
    }

    @Override
    public void handlerRequest(Request request) {
        if(RequestType.valueOf(request.getRequestType())!=null && request.getMoney()>10000){

            System.out.println("大额操作,输入支付密码+验证码+人脸识别 ");

            System.out.println(name+":"+request.getRequestType() + ", 金额:"+request.getMoney() +" 处理完成");

        }else {
            //下个节点进行处理
            if(superior!=null){
                superior.handlerRequest(request);
            }
        }
    }
}

测试

public static void main(String[] args) {
        RiskControlManager firstControlManager = new FirstRiskControlManager("初级风控");

        RiskControlManager secondControlManager = new SecondRiskControlManager("中级风控");

        RiskControlManager thirdControlManager = new ThirdRiskControlManager("高级风控");

        //形成调用链
        firstControlManager.setSuperior(secondControlManager);
        secondControlManager.setSuperior(thirdControlManager);
        //使用
        Request request1 = new Request();
        request1.setRequestType(RequestType.CASH_OUT.name());
        request1.setMoney(21000);
        firstControlManager.handlerRequest(request1);
    }

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1122004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试(基础篇)——解构Java常见的基础面试题 结合Java源码分析

fail-safe 和fail-fast机制 Fail-fast&#xff1a;快速失败 Fail-fast &#xff1a; 表示快速失败&#xff0c;在集合遍历过程中&#xff0c;一旦发现容器中的数据被修改了&#xff0c;会立刻抛出ConcurrentModificationException 异常&#xff0c;从而导致遍历失败 package …

经典链表问题:解析链表中的关键挑战

这里写目录标题 公共子节点采用集合或者哈希采用栈拼接两个字符串差和双指针 旋转链表 公共子节点 例如这样一道题&#xff1a;给定两个链表&#xff0c;找出它们的第一个公共节点。 具体的题目描述我们来看看牛客的一道题&#xff1a; 这里我们有四种解决办法&#xff1a; …

Tomcat启动控制台乱码问题

修改Tomcat/conf/logging.properties

[C++] C++入门

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C和Linux &#x1f33c;博客专栏&#xff1a;C入门 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&#x1f3fb; …

【Mysql】B+树索引的使用(七)

前言 每个索引都对应一棵 B 树&#xff0c; B 树分为多层&#xff0c;最下边一层是叶子节点&#xff0c;其余的是内节点&#xff08;非叶子节点&#xff09;。所有用户记录都存储在 B 树的叶子节点&#xff0c;所有目录项记录都存储在内节点。 InnoDB 存储引擎会自动为主键&am…

Spring Cloud Alibaba Seata 实现分布式事物

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案 Seata 官网&#xff1a;https://seata.io/zh-cn/ Spring Cloud Alibaba 官…

信息检索与数据挖掘 | (五)文档评分、词项权重计算及向量空间模型

目录 &#x1f4da;词项频率及权重计算 &#x1f407;词项频率 &#x1f407;逆文档频率 &#x1f407;tf-idf权重计算 &#x1f4da;向量空间模型 &#x1f407;余弦相似度 &#x1f407;查询向量 &#x1f407;向量相似度计算 &#x1f4da;其他tf-idf权值计算方法 …

【OpenGL】五、光照

OpenGL Lighting 文章目录 OpenGL Lighting一、 冯氏光照模型(Phong Lighting Model)环境光&#xff08;Ambient lighting&#xff09;漫反射光照&#xff08;Diffuse lighting&#xff09;漫反射光照&#xff08;Specular Lighting&#xff09; 二、 材质(Materials)光照贴图(…

JUC并发编程笔记2

省流&#xff1a; 自己笔记&#xff0c;划走~~~~ 缓存更新策略

vue3里面vant组件的标签页使用?

一、绑一个v-model事件 二、让activeName的初始为0也就是默认是显示第一个标签页的下标 三、给标签页下面的东西进行一个判断 想让哪个优先显示就把哪个判断作为初始值存入

【试题040】多个逻辑或例题2

1.题目&#xff1a;设int n0;&#xff0c;执行表达式n ||(n-1) ||(n0)||(n1)||(n2)后n的值是 &#xff1f; 2.代码解析&#xff1a; 逻辑或 || 运算符是一个短路运算符&#xff0c;它从左到右依次计算表达式&#xff0c;如果遇到一个为真&#xff08;非零&#xff09;的值&am…

No171.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

第一章概述

一、学习目的与要求 本章对软件测试作了概括性的介绍&#xff0c;目的是使学生对软件测试有个初步的认识。通过本章的学习&#xff0c;应使学生掌握软件测试的基本概念&#xff0c;了解软件测试的发展历程和行业现状&#xff0c;掌握软件测试技术的分类&#xff0c;理解软件测试…

【JAVA-Day49】Java LinkedList集合详解

Java LinkedList集合详解 摘要引言Java LinkedList集合详解一、什么是LinkedList集合1.1 链表数据结构1.2 双向链表1.3 动态大小1.4 插入和删除元素1.5 适用场景 二、LinkedList集合的使用2.1 创建 LinkedList 集合、添加元素、遍历元素2.2 在指定位置插入元素2.3 获取指定位置…

模拟 Junit 框架

需求 定义若干个方法&#xff0c;只要加了MyTest注解&#xff0c;就可以在启动时被触发执行 分析 定义一个自定义注解MyTest&#xff0c;只能注解方法&#xff0c;存活范围是一直都在定义若干个方法&#xff0c;只要有MyTest注解的方法就能在启动时被触发执行&#xff0c;没有这…

开源博客项目Blog .NET Core源码学习(5:mapster使用浅析)

开源博客项目Blog使用mapster框架映射对象&#xff0c;主要是在数据库表对象及前端数据对象之间进行映射&#xff0c;本文学习并记录项目中mapster的使用方式。   App.Hosting项目的program文件中调用builder.Services.AddMapper函数进行对象模型自动映射&#xff0c;而该函数…

numpy矩阵画框框

在n>5(n是奇数)的nn数组中&#xff0c;用*画外方框和内接菱形。 (本笔记适合熟悉numpy的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那…

二维码智慧门牌管理系统升级解决方案:突破传统,实现质检与抽检的个性化配置

文章目录 前言一、引入“独立质检”二、个性化抽检类别设定三、触发重采要素的功能升级四、升级优势与展望 前言 在数字化时代&#xff0c;智慧门牌管理系统已经成为社会管理的重要工具。为了满足各种复杂需求&#xff0c;系统升级是必然趋势。本次升级主要针对质检和抽检两大…

Python+requests+exce接口自动化测试框架

一、接口自动化测试框架 二、工程目录 三、Excel测试用例设计 四、基础数据base 封装post/get&#xff1a;runmethod.py #!/usr/bin/env python3 # -*-coding:utf-8-*- # __author__: hunterimport requests import jsonclass RunMain:def send_get(self, url, data):res req…