设计模式之责任链的通用实践思考

责任链模式通常一般用在方法的拦截、监控、统计方面,比较典型的就是Spring的AOP拦截。
但写一些小的基础能力框架的时候,用AOP比较中,所以一般都是自己针对特定的功能写一些定制的责任链工具类,不太喜欢总是做一些定制化的东西,想着能不能简单定义一套标准,基于标准能够快速实现责任链的能力?

1、定义简单的链路控制类

该类是一套标准的控制类,主要负责流转链路执行走向
其中Supplier中是目标的执行方法
T 代表接口的标记也就是第二点的实现

public class SampleBaseFilterChain<T extends SimpleChainFilterService> {/*** 拦截器*/private final List<T> functionFilters;/*** 具体的执行方法*/private final Supplier<Object> supplier;private int index = 0;public SampleBaseFilterChain(List<T> functionFilters, Supplier<Object> supplier) {this.functionFilters = functionFilters;this.supplier = supplier;}// 该方法是为了方便在Spring的IOC容器中直接根据类对象,从容器中获取相应的集合.public SampleBaseFilterChain(Class<T> clazz, Supplier<Object> supplier) {this.functionFilters = SpringUtils.getBeansOfType(clazz).values().stream().toList();this.supplier = supplier;}public Object doFilter(Object... objects) {if (CollectionUtils.isEmpty(functionFilters) || functionFilters.size() == index) {return supplier.get();}return functionFilters.get(index++).doFilter(this, objects);}}

2、定义接口标准

这部分接口太过于抽象,比如你不知道参数具体是啥,可能需要针对下层实现才知道。

public interface SimpleChainFilterService {Object doFilter(SampleBaseFilterChain<? extends SimpleChainFilterService> chain, Object... obj);
}

基于以上两点基本上确定了控制器和顶层接口的定义,该怎么玩呢?

@Testpublic void doFilter() {List<SimpleChainFilterService> chainList = new ArrayList<>();chainList.add((chain, obj) -> {System.out.println("A-start-" + obj[0]);return chain.doFilter(obj);});chainList.add((chain, obj) -> {final Object o = chain.doFilter(obj);System.out.println("B-end-" + obj[0]);return o;});chainList.add((chain, obj) -> {System.out.println("C-start-" + obj[1]);final Object o = chain.doFilter(obj);System.out.println("C-end-" + obj[1]);return o;});SampleBaseFilterChain<SimpleChainFilterService> sampleFilterChain = new SampleBaseFilterChain<>(chainList, () -> "ok");final Object o = sampleFilterChain.doFilter("哈哈", 1);System.out.println("得到结果:" + o);}

打印结果:

A-start-哈哈
C-start-1
C-end-1
B-end-哈哈
得到结果:ok

3、接口标准优化

对于第二点的接口,太过于抽象,无法知道接口的具体参数,这对后续使用者实现来说会很麻烦。
这个时候,你可以针对特定的业务标准在下沉一层。
比如需要针对登录进行拦截

public interface  LoginChain extends SimpleChainFilterService {@Overridedefault Object doFilter(SampleBaseFilterChain<? extends SimpleChainFilterService> chain, Object... obj) {return doFilter(chain, (String) obj[0], (int) obj[1]);}public String doFilter(SampleBaseFilterChain<? extends SimpleChainFilterService> chain, String username, int id);
}

使用方式:

// 前置拦截
List<LoginChain1> chainList1 = new ArrayList<>();
chainList1.add((chain, username, id) -> {System.out.println("login-start-" + username + "\t" + id);return chain.doFilter(username, id).toString();
});// 后置拦截
chainList1.add((chain, username, id) -> {final String result = chain.doFilter(username, id).toString();System.out.println("login-end-" + username + "\t" + id);return result;
});SampleBaseFilterChain<LoginChain1> sampleFilterChain = new SampleBaseFilterChain<>(chainList1, () -> {System.out.println("ok");return "ok";
});final Object o = sampleFilterChain.doFilter("哈哈", 1);
System.out.println("得到结果:" + o);
login-start-哈哈	1
ok
login-end-哈哈	1
得到结果:ok

基于以上的定义,我们只需要编写SimpleChainFilterService实现即可,通过使用SampleBaseFilterChain 来触发控制流程的流转,就行了,不用每套责任链都要重写接口和控制链。

以上为个人实践思考,如果你有更好的方式,欢迎交流学习~

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

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

相关文章

pandas——对齐运算+函数应用

引言&#xff1a;对齐运算是数据清洗的重要过程&#xff0c;可以按索引对齐进行运算&#xff0c;如果没对齐的位置则补NaN&#xff0c;最后也可以填充NaN 一、Series的对齐运算 1.Series 按行、索引对齐 import pandas as pds1 pd.Series(range(10, 20), indexrange(10)) s2…

画动态爱心(Python-matplotlib)

介绍 氵而已 由于用的是 AI&#xff0c;注释得非常清楚&#xff0c;自己改改也可以用 代码 # -*- coding: utf-8 -*- # Environment PyCharm # File_name 尝试1 |User Pfolg # 2024/11/05 22:45 import numpy as np import matplotlib.pyplot as plt import matplot…

学习threejs,将多个网格合并成一个网格

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.Geometry 几何体1.2 …

对于一个需要渲染300帧的动画项目,云渲染要多久

探讨云渲染动画300帧需要多久的问题时&#xff0c;我们今天来从多个角度进行分析&#xff0c;对于一个需要渲染300帧的动画项目&#xff0c;传统的本地渲染方式可能会因为硬件限制而变得耗时且效率低下。幸运的是&#xff0c;【渲染101】云渲染技术的出现为这一问题提供了解决方…

系统上云-流量分析和链路分析

优质博文&#xff1a;IT-BLOG-CN 一、流量分析 【1】流量组成&#xff1a; 按协议划分&#xff0c;流量链路可分为HTTP、SOTP、QUIC三类。 HTTPSOTPQUIC场景所有HTTP请求&#xff0c;无固定场景国内外APP等海外APP端链路选择DNS/CDN(当前特指Akamai)APP端保底IP列表/动态IP下…

「Mac畅玩鸿蒙与硬件22」鸿蒙UI组件篇12 - Canvas 组件的动态进阶应用

在鸿蒙应用中&#xff0c;Canvas 组件可以实现丰富的动态效果&#xff0c;适合用于动画和实时更新的场景。本篇将介绍如何在 Canvas 中实现动画循环、动态进度条、旋转和缩放动画&#xff0c;以及性能优化策略。 关键词 Canvas 组件动态绘制动画效果动态进度条旋转和缩放性能优…

C 学习(4)

return 0; 前提&#xff1a;C 语言规定&#xff0c;main()是程序的入口函数&#xff0c;即所有的程序一定要包含一个main()函数。程序总是从这个函数开始执行&#xff0c;如果没有该函数&#xff0c;程序就无法启动。其他函数都是通过它引入程序的。 main()的写法&#xff0c…

Springboot3.3 + Mybatis / Mybatis-plus

Java17, Springboot 3.3.5, 项目一启动就报错&#xff1a; Invalid value type for attribute factoryBeanObjectType: java.lang.String 我知道问题出现在pom依赖的版本上。但网上对于Springboot3.3的配置资料并不多&#xff0c;且在我代码上实测还是会报错。搞了一天终于…

高亚科技签约酸动力,助力研发管理数字化升级

近日&#xff0c;中国企业管理软件资深服务商高亚科技与广东酸动力生物科技有限公司&#xff08;以下简称“酸动力”&#xff09;正式签署合作协议。借助高亚科技的8Manage PM项目管理软件&#xff0c;酸动力将进一步优化项目过程跟踪与节点监控&#xff0c;提升研发成果的高效…

java多线程编程(二)一一>线程安全问题, 单例模式, 解决程线程安全问题的措施

引言&#xff1a; 如果多线程环境下代码运行的结果是符合我们预期的&#xff0c;即在单线程环境应该的结果&#xff0c;则说这个程序是线程安全的 线程安全问题的原因&#xff1a; 一.操作系统的随机调度 &#xff1a; 二.多个线程修改同一个变量&#xff1a; 三.修改操作不是…

推荐一款非常好用的视频编辑软件:Movavi Video Editor Plus

MovaviVideoEditorPlus(视频编辑软件)可以制作令人惊叹的视频&#xff0c;即使您没有任何视频编辑方面的经验! 该款视频编辑程序没有复杂的设置&#xff0c;只需进行直观的拖放控制。在您的电脑上免费使用MovaviVideoEditor亲身体验它的简单易用性与强大功能! 基本简介 您是否…

【算法】递归+深搜+哈希表:889.根据前序和后序遍历构造二叉树

目录 1、题目链接 相似题目: 2、题目 ​3、解法&#xff08;针对无重复值&#xff0c;哈希表递归&#xff09; 函数头-----找出重复子问题 函数体---解决子问题 4、代码 1、题目链接 889.根据前序和后序遍历构造二叉树&#xff08;LeetCode&#xff09; 相似题目: 105.…

高级信号完整性

高级信号完整性&#xff0c;2022年版&#xff0c;1473页&#xff0c;24h秒发 内容庞大&#xff0c;都是新的内容、架构 QS排名100内的美国高校课件 发货内容&#xff1a; 29个分章节PDF 1个汇总PDF&#xff0c;1473页 点击获取 课程首先对电磁学进行了回顾。随后&#xff0c;…

yelp数据集上识别潜在的热门商家

yelp数据集是研究B2C业态的一个很好的数据集&#xff0c;要识别潜在的热门商家是一个多维度的分析过程&#xff0c;涉及用户行为、商家特征和社区结构等多个因素。从yelp数据集里我们可以挖掘到下面信息有助于识别热门商家 用户评分和评论分析 评分均值: 商家的平均评分是反映其…

qt QDataStream详解

1. 概述 QDataStream是Qt框架中的一个核心类&#xff0c;主要用于处理二进制数据的序列化和反序列化。它提供了高效、跨平台的方式&#xff0c;将C数据结构转化为字节流&#xff0c;便于在网络传输、持久化存储等场景下使用。QDataStream可以处理包括整数、浮点数、布尔值、字…

使用Spring Validation实现数据校验详解

目录 前言1. Spring Validation概述2. 配置Spring Validation2.1 引入依赖2.2 启用全局校验 3. 使用注解进行参数校验3.1 基本校验注解3.2 使用Pattern进行正则校验3.3 综合示例 4. 在控制器层应用校验4.1 方法参数校验4.2 自定义错误处理 5. 高级应用&#xff1a;自定义校验注…

链表(C 语言)

目录 一、链表的概念1. 链表的结构2. 链表的分类3. 链表的优势 二、链表的实现1. 无头单项非循环链表的实现1.1 代码说明 2. 带头双向循环链表的实现2.1 代码说明 三、链表和顺序表的区别四、链表总结 一、链表的概念 链表是一种顺序表&#xff0c;它由一个一个的节点组成&…

QinQ的基础实验

拓扑 命令 LSW1 [LSW1]vlan batch 2 3 4 Info: This operation may take a few seconds. Please wait for a moment...done. [LSW1]interface g0/0/1 [LSW1-GigabitEthernet0/0/1]port link-type hybrid [LSW1-GigabitEthernet0/0/1]port hybrid untagged vlan 2 3 [LSW…

python-读写Excel:openpyxl-(4)下拉选项设置

使用openpyxl库的DataValidation对象方法可添加下拉选择列表。 DataValidation参数说明&#xff1a; type&#xff1a; 数据类型("whole", "decimal", "list", "date", "time", "textLength", "custom"…

Elasticsearch中时间字段格式用法详解

Elasticsearch中时间字段格式用法详解 攻城狮Jozz关注IP属地: 北京 2024.03.18 16:27:51字数 758阅读 2,571 Elasticsearch&#xff08;简称ES&#xff09;是一个基于Lucene构建的开源、分布式、RESTful搜索引擎。它提供了全文搜索、结构化搜索以及分析等功能&#xff0c;广泛…