当前位置: 首页 > news >正文

责任链设计模式(单例+多例)

目录

1. 单例责任链

2. 多例责任链

核心区别对比

实际应用场景

单例实现

多例实现

初始化

初始化责任链

执行测试方法


欢迎关注我的博客!26届java选手,一起加油💘💦👨‍🎓😄😂

最近在学习项目的时候学到了责任链的设计模式,觉得很有趣,但对我来说也很有挑战,写一篇文章记录我是如何弄懂这个设计模式和带着例子的全链路解析。

责任链模式,责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求。在这个具体的代码中,主要用于构建一个规则处理链,不同的规则可以依次处理请求。

单例责任链和多例责任链的区别主要体现在实例管理方式应用场景上,以下是具体对比:

1. 单例责任链

  • 定义:整个责任链在系统中全局唯一,所有请求共享同一个链实例,链中的每个节点(处理者)也通常是单例。
  • 特点
    • 线程安全风险:若责任链允许动态修改(如追加节点),需考虑线程安全问题(如使用 ConcurrentHashMap 或加锁)。
    • 固定结构:链结构一旦初始化完成,通常不会改变(除非主动修改)。
    • 资源高效:内存中仅存在一个链实例,适合稳定且高频使用的场景。
  • 示例

    java

    @Service
    public class Rule01TradeRuleFactory {@Resource private RuleLogic101 ruleLogic101;@Resource private RuleLogic102 ruleLogic102;public ILogicLink openLogicLink() {// 单例链:全局共享同一个 ruleLogic101 和 ruleLogic102 实例ruleLogic101.appendNext(ruleLogic102); return ruleLogic101;}
    }
    

2. 多例责任链

  • 定义:每次使用责任链时动态创建新实例,链结构和节点可能每次不同。
  • 特点
    • 线程安全:每个链实例独立,无并发问题。
    • 灵活性高:可根据需求动态组合节点(如 A→B→C 或 A→C)。
    • 资源消耗:每次创建新链,适合低频或需要灵活配置的场景。
  • 示例

    java

    @Service
    public class MultiInstanceRuleFactory {@Resource private RuleLogic101 ruleLogic101;@Resource private RuleLogic102 ruleLogic102;public ILogicLink createLink(boolean useNode2) {// 多例链:每次返回新的链结构RuleLogic101 newNode1 = new RuleLogic101(); if (useNode2) {newNode1.appendNext(new RuleLogic102()); }return newNode1;}
    }
    

核心区别对比

维度单例责任链多例责任链
实例数量全局唯一每次使用时创建新实例
结构灵活性固定(需手动修改)动态组合(如条件添加节点)
线程安全需额外处理(如加锁)天然线程安全
适用场景高频、稳定的请求处理低频、动态配置的请求处理
资源消耗较高(每次创建新对象)

实际应用场景

  • 单例责任链:电商风控规则链、支付流程校验链(规则固定且高频调用)。
  • 多例责任链:动态任务编排、个性化业务流程(如用户自定义审批流)。

单例实现

ILogicChainArmory<T, D, R>:该接口定义了责任链的基本操作,即获取下一个处理者(next())和追加下一个处理者(appendNext())。这样的设计使得责任链中的每个处理者都可以动态地连接其他处理者,形成一个链式结构。

ILogicLink<T, D, R>:继承自 ILogicChainArmory<T, D, R>,并额外定义了 apply 方法,用于处理请求。apply 方法接收请求参数 requestParameter 和动态上下文 dynamicContext,并返回处理结果。

AbstractLogicLink<T, D, R>:实现了 ILogicLink<T, D, R> 接口,提供了 next 属性和 next()appendNext() 方法的基本实现。同时,还提供了一个受保护的 next 方法,用于调用下一个处理者的 apply 方法,从而实现请求的传递。

public interface ILogicChainArmory<T, D, R> {ILogicLink<T, D, R> next();ILogicLink<T, D, R> appendNext(ILogicLink<T, D, R> next);}public interface ILogicLink<T, D, R> extends ILogicChainArmory<T, D, R> {R apply(T requestParameter, D dynamicContext) throws Exception;}public abstract class AbstractLogicLink<T, D, R> implements ILogicLink<T, D, R> {private ILogicLink<T, D, R> next;@Overridepublic ILogicLink<T, D, R> next() {return next;}@Overridepublic ILogicLink<T, D, R> appendNext(ILogicLink<T, D, R> next) {this.next = next;return next;}protected R next(T requestParameter, D dynamicContext) throws Exception {return next.apply(requestParameter, dynamicContext);}}

具体实现:

定义两个实现:

@Slf4j
@Service
public class RuleLogic101 extends AbstractLogicLink<String, Rule02TradeRuleFactory.DynamicContext, String>{@Overridepublic String apply(String requestParameter, Rule01TradeRuleFactory.DynamicContext dynamicContext) throws Exception {log.info("link model01 RuleLogic101");return next(requestParameter, dynamicContext);}}@Slf4j
@Service
public class RuleLogic102 extends AbstractLogicLink<String, Rule02TradeRuleFactory.DynamicContext, String>{@Overridepublic String apply(String requestParameter, Rule01TradeRuleFactory.DynamicContext dynamicContext) throws Exception {log.info("link model01 RuleLogic102");return "link model01 单实例链";}}

Rule01TradeRuleFactory 类是一个工厂类,它的主要作用是创建和组装责任链。在这个责任链中,RuleLogic101 和 RuleLogic102 是具体的规则处理器,通过工厂类将它们连接成一个链,以便按顺序处理请求。

@Service
public class Rule01TradeRuleFactory {@Resourceprivate RuleLogic101 ruleLogic101;@Resourceprivate RuleLogic102 ruleLogic102;public ILogicLink<String, Rule02TradeRuleFactory.DynamicContext, String> openLogicLink() {ruleLogic101.appendNext(ruleLogic102);return ruleLogic101;}@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic static class DynamicContext {private String age;}}

测试方法

    @Testpublic void test_model01_01() throws Exception {ILogicLink<String, Rule02TradeRuleFactory.DynamicContext, String> logicLink = rule01TradeRuleFactory.openLogicLink();String logic = logicLink.apply("123", new Rule02TradeRuleFactory.DynamicContext());log.info("测试结果:{}", JSON.toJSONString(logic));}

执行openLogicLink方法

在执行appenNext的时候进行责任链的组装:RuleLogic101->RuleLogic102,并返回

然后就能执行责任链头节点的apply方法,这里return next()就是在AbstractLogicLink里的

protected R next(T requestParameter, D dynamicContext) throws Exception {return next.apply(requestParameter, dynamicContext);}

也就是去执行了RuleLogic102的apply方法:

到此单例的责任链就结束

多例实现


链表接口:

public interface ILink<E> {boolean add(E e);boolean addFirst(E e);boolean addLast(E e);boolean remove(Object o);E get(int index);void printLinkList();}

链表实现

/*** @description 双向链表基础实现类(责任链的底层数据结构)* @param <E> 链表存储的元素类型(这里为 ILogicHandler 实现类)*/
public class LinkedList<E> implements ILink<E> {/** 链表名称(用于标识不同责任链) */private final String name;/** 链表元素数量(transient 表示序列化时忽略该字段) */transient int size = 0;/** 头节点引用 */transient Node<E> first;/** 尾节点引用 */transient Node<E> last;/*** 构造函数* @param name 链表名称*/public LinkedList(String name) {this.name = name;}// ============================ 节点操作方法 ============================/*** 在链表头部插入新节点* @param e 待插入的元素*/private void linkFirst(E e) {final Node<E> oldFirst = first; // 保存原头节点final Node<E> newNode = new Node<>(null, e, oldFirst); // 创建新节点,前驱为 null,后继为原头节点first = newNode; // 更新头节点为新节点// 若原头节点为空(链表为空)if (oldFirst == null) {last = newNode; // 同时更新尾节点} else {oldFirst.prev = newNode; // 原头节点的前驱指向新节点}size++; // 元素数量加 1}/*** 在链表尾部插入新节点* @param e 待插入的元素*/private void linkLast(E e) {final Node<E> oldLast = last; // 保存原尾节点final Node<E> newNode = new Node<>(oldLast, e, null); // 创建新节点,前驱为原尾节点,后继为 nulllast = newNode; // 更新尾节点为新节点// 若原尾节点为空(链表为空)if (oldLast == null) {first = newNode; // 同时更新头节点} else {oldLast.next = newNode; // 原尾节点的后继指向新节点}size++; // 元素数量加 1}// ============================ ILink 接口实现 ============================/*** 默认将元素添加到链表尾部(接口方法)* @param e 待添加的元素* @return 添加成功返回 true*/@Overridepublic boolean add(E e) {linkLast(e); // 调用尾部插入方法return true;}/*** 在链表头部添加元素(接口方法)* @param e 待添加的元素* @return 添加成功返回 true*/@Overridepublic boolean addFirst(E e) {linkFirst(e); // 调用头部插入方法return true;}/*** 在链表尾部添加元素(接口方法)* @param e 待添加的元素* @return 添加成功返回 true*/@Overridepublic boolean addLast(E e) {linkLast(e); // 调用尾部插入方法return true;}/*** 根据元素值删除节点(接口方法)* @param o 待删除的元素值* @return 删除成功返回 true*/@Overridepublic boolean remove(Object o) {// 处理 null 值的情况if (o == null) {for (Node<E> x = first; x != null; x = x.next) {if (x.item == null) { // 找到值为 null 的节点unlink(x); // 删除该节点return true;}}} else {// 处理非 null 值的情况for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item)) { // 找到值匹配的节点unlink(x); // 删除该节点return true;}}}return false; // 未找到匹配节点}/*** 内部删除节点的方法* @param x 待删除的节点* @return 被删除节点的元素值*/private E unlink(Node<E> x) {final E element = x.item; // 保存节点值final Node<E> nextNode = x.next; // 保存后继节点final Node<E> prevNode = x.prev; // 保存前驱节点// 更新前驱节点的后继指针if (prevNode == null) {first = nextNode; // 若无前驱,删除的是头节点,更新头节点} else {prevNode.next = nextNode; // 前驱节点的后继指向后继节点x.prev = null; // 断开当前节点的前驱}// 更新后继节点的前驱指针if (nextNode == null) {last = prevNode; // 若无比后继,删除的是尾节点,更新尾节点} else {nextNode.prev = prevNode; // 后继节点的前驱指向前驱节点x.next = null; // 断开当前节点的后继}x.item = null; // 帮助垃圾回收size--; // 元素数量减 1return element; // 返回被删除的元素值}/*** 根据索引获取元素(接口方法)* @param index 元素索引* @return 对应位置的元素*/@Overridepublic E get(int index) {return node(index).item; // 先找到节点,再返回其值}/*** 根据索引查找节点(优化查找方向)* @param index 节点索引* @return 对应的节点*/Node<E> node(int index) {// 如果索引在前半部分,从头部开始查找if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++) {x = x.next; // 向后移动指针}return x;} else {// 如果索引在后半部分,从尾部开始查找Node<E> x = last;for (int i = size - 1; i > index; i--) {x = x.prev; // 向前移动指针}return x;}}// ============================ 辅助方法 ============================/*** 打印链表结构(调试用)*/public void printLinkList() {if (size == 0) {System.out.println("链表为空");return;}Node<E> temp = first;System.out.printf("链表名称:%s,头节点:%s,尾节点:%s,整体:", name, first.item, last.item);while (temp != null) {System.out.print(temp.item + " → ");temp = temp.next;}System.out.println("null");}// ============================ 内部节点类 ============================/*** 链表节点结构(静态内部类)* @param <E> 节点存储的元素类型*/protected static class Node<E> {E item;        // 节点存储的值Node<E> next;  // 后继节点引用Node<E> prev;  // 前驱节点引用/*** 节点构造函数* @param prev 前驱节点* @param element 存储的值* @param next 后继节点*/public Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}}// ============================ Getter 方法 ============================/*** 获取链表名称* @return 链表名称*/public String getName() {return name;}
}

业务链路BusinessLinkedList

public class BusinessLinkedList<T, D, R> extends LinkedList<ILogicHandler<T, D, R>> implements ILogicHandler<T, D, R>{public BusinessLinkedList(String name) {super(name);}@Overridepublic R apply(T requestParameter, D dynamicContext) throws Exception {Node<ILogicHandler<T, D, R>> current = this.first;do {ILogicHandler<T, D, R> item = current.item;R apply = item.apply(requestParameter, dynamicContext);if (null != apply) return apply;current = current.next;} while (null != current);return null;}}

业务链路ILogicHandler

public interface ILogicHandler<T, D, R> {default R next(T requestParameter, D dynamicContext) {return null;}R apply(T requestParameter, D dynamicContext) throws Exception;}

 链路装配:

public class LinkArmory<T, D, R> {private final BusinessLinkedList<T, D, R> logicLink;@SafeVarargspublic LinkArmory(String linkName, ILogicHandler<T, D, R>... logicHandlers) {logicLink = new BusinessLinkedList<>(linkName);for (ILogicHandler<T, D, R> logicHandler: logicHandlers){logicLink.add(logicHandler);}}public BusinessLinkedList<T, D, R> getLogicLink() {return logicLink;}}

初始化

首先有一个责任链工厂:

demo01是假设有两个节点的责任链,demo2是假设只有一个节点的责任链,

@Service
public class Rule02TradeRuleFactory {@Bean("demo01")public BusinessLinkedList<String, DynamicContext, XxxResponse> demo01(RuleLogic201 ruleLogic201, RuleLogic202 ruleLogic202) {LinkArmory<String, DynamicContext, XxxResponse> linkArmory = new LinkArmory<>("demo01", ruleLogic201, ruleLogic202);return linkArmory.getLogicLink();}@Bean("demo02")public BusinessLinkedList<String, DynamicContext, XxxResponse> demo02(RuleLogic202 ruleLogic202) {LinkArmory<String, DynamicContext, XxxResponse> linkArmory = new LinkArmory<>("demo02", ruleLogic202);return linkArmory.getLogicLink();}@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic static class DynamicContext {private String age;}}//在这里接受上面@Bean注解的注入,并且完成装配链表的工作
public class LinkArmory<T, D, R> {private final BusinessLinkedList<T, D, R> logicLink;@SafeVarargspublic LinkArmory(String linkName, ILogicHandler<T, D, R>... logicHandlers) {logicLink = new BusinessLinkedList<>(linkName);for (ILogicHandler<T, D, R> logicHandler: logicHandlers){logicLink.add(logicHandler);}}public BusinessLinkedList<T, D, R> getLogicLink() {return logicLink;}}

测试方法:

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class Link02Test {@Resource(name = "demo01")private BusinessLinkedList<String, Rule02TradeRuleFactory.DynamicContext, XxxResponse> businessLinkedList01;@Resource(name = "demo02")private BusinessLinkedList<String, Rule02TradeRuleFactory.DynamicContext, XxxResponse> businessLinkedList02;@Testpublic void test_model02_01() throws Exception {XxxResponse apply = businessLinkedList01.apply("123", new Rule02TradeRuleFactory.DynamicContext());log.info("测试结果:{}", JSON.toJSONString(apply));}@Testpublic void test_model02_02() throws Exception {XxxResponse apply = businessLinkedList02.apply("123", new Rule02TradeRuleFactory.DynamicContext());log.info("测试结果:{}", JSON.toJSONString(apply));}}

执行流程:两只节点的情况:

初始化责任链

在工厂里装配demo01的两个节点,

 @Bean("demo01")public BusinessLinkedList<String, DynamicContext, XxxResponse> demo01(RuleLogic201 ruleLogic201, RuleLogic202 ruleLogic202) {LinkArmory<String, DynamicContext, XxxResponse> linkArmory = new LinkArmory<>("demo01", ruleLogic201, ruleLogic202);return linkArmory.getLogicLink();}

进入LinkArmory的构造方法:遍历节点并添加:

执行linkArmory.getLogicLink(); 获取这个责任链:

执行测试方法

从这里获取注入的bean,获取到责任链

@Resource(name = "demo01")private BusinessLinkedList<String, Rule02TradeRuleFactory.DynamicContext, XxxResponse> businessLinkedList01;@Testpublic void test_model02_01() throws Exception {XxxResponse apply = businessLinkedList01.apply("123", new Rule02TradeRuleFactory.DynamicContext());log.info("测试结果:{}", JSON.toJSONString(apply));}

执行BusinessLinkedListz中的apply方法,就是遍历责任链,挨个执行apply方法,直到执行到最后有返回值的时候就停止:

然后会执行各个节点的apply方法,并且去往下一个节点

在ILogicHandler的next是直接返回null的,然后再经过判断:

default R next(T requestParameter, D dynamicContext) {return null;}

返回的是null就会继续遍历下一个节点:如果不是null就会结束,并把返回值返回。

相关文章:

责任链设计模式(单例+多例)

目录 1. 单例责任链 2. 多例责任链 核心区别对比 实际应用场景 单例实现 多例实现 初始化 初始化责任链 执行测试方法 欢迎关注我的博客&#xff01;26届java选手&#xff0c;一起加油&#x1f498;&#x1f4a6;&#x1f468;‍&#x1f393;&#x1f604;&#x1f602; 最近在…...

Matlab 分数阶PID控制永磁同步电机

1、内容简介 Matlab 203-分数阶PID控制永磁同步电机 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...

Java中LocalDateTime类

Java中的日期类 Date类LocalDateTime类创建LocalDateTime对象1 获取当前时间2 获取自己指定时间3 字符串创建日期 获取当前日期的信息1获取当前日期的年月日 时分秒2 获取当前日期周几\当年第几天\当月第几天3 获取当前⽇期所在周的周⽇和周⼀ 日期的运算1日期加减天数2 日期加…...

【C语言】--- 文件操作

文件操作 1. 为什么要使用文件2. 什么是文件2.1 程序文件2.2 数据文件2.3 文件名 3. 二进程文件和文本文件4. 文件的打开和关闭4.1 流和标准流4.1.1流4.2.2标准流 4.2 文件指针4.3 打开和关闭操作 5. 文件的顺序读写5.1 文件顺序读写函数5.1.1 fgetc 和 fputc5.1.2 fgets 和 fg…...

操作系统 4.4-从生磁盘到文件

文件介绍 操作系统中对磁盘使用的第三层抽象——文件。这一层抽象建立在盘块&#xff08;block&#xff09;和文件&#xff08;file&#xff09;之间&#xff0c;使得用户可以以更直观和易于理解的方式与磁盘交互&#xff0c;而无需直接处理磁盘的物理细节如扇区&#xff08;se…...

第六章 进阶03 外包测试亮相

因为有年度重点项目&#xff0c;团队缺少测试资源&#xff0c;所以临时招聘了一个外包测试&#xff08;后文用J代指&#xff09;&#xff0c;让产品经理亮亮来带她。 到今天J差不多入职有1个月时间了&#xff0c;亮亮组了个会&#xff0c;一起评审下J做的测试用例。 J展示了其…...

如何使用通义灵码完成PHP单元测试 - AI辅助开发教程

一、引言 在软件开发过程中&#xff0c;测试是至关重要的一环。然而&#xff0c;在传统开发中&#xff0c;测试常常被忽略或草草处理&#xff0c;很多时候并非开发人员故意为之&#xff0c;而是缺乏相应的测试思路和方法&#xff0c;不知道如何设计测试用例。随着 AI 技术的飞…...

使用 nano 文本编辑器修改 ~/.bashrc 文件与一些快捷键

目录 使用 nano 编辑器保存并关闭文件使用 sed 命令直接修改文件验证更改 如果你正在使用 nano 文本编辑器来修改 ~/.bashrc 文件&#xff0c;以下是保存并关闭文件的具体步骤&#xff1a; 使用 nano 编辑器保存并关闭文件 打开 ~/.bashrc 文件 在终端中运行以下命令&#xf…...

计算机组成原理——CPU与存储器连接例题

计算机组成原理——CPU与存储器连接例题 设CPU共有16根地址线和8根数据线&#xff0c;并用(MREQ) ̅作为访存控制信号&#xff08;低电平有效&#xff09;&#xff0c;(WR) ̅作为读/写命令信号&#xff08;高电平读&#xff0c;低电平写&#xff09;。现有下列存储芯片&#…...

SQL 外键(Foreign Key)详细讲解

1. 什么是外键&#xff1f;​​ ​​定义​​&#xff1a;外键是数据库表中的一列&#xff08;或一组列&#xff09;&#xff0c;用于​​建立两个表之间的关联关系​​。外键的值必须匹配另一个表的主键&#xff08;Primary Key&#xff09;或唯一约束&#xff08;Unique Con…...

B3647 【模板】Floyd

题目链接&#xff1a;点击进入 题目 思路 代码 #include <bits/stdc.h> #define inf 0x3f3f3f3f using namespace std; const int maxn 1e6 10;int n,m,g[110][5000];int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m;memse…...

配置镜像端口和观察接口

top&#xff1a; 在G0/0/2上抓包通过其他端口ping pc4 可以看到 Wireshark 抓包没有任何反应&#xff0c;做个镜像端口并配置&#xff08;观察接口和镜像接口&#xff09; observe-port interface g0/0/2 #命令配置观察端口mirror to observe-port both …...

爬虫解决debbugger之替换文件

鼠鼠上次做一个网站的时候&#xff0c;遇到的debbugger问题&#xff0c;是通过打断点然后编辑断点解决的&#xff0c;现在鼠鼠又学会了一个新的技能 首先需要大家下载一个reres的插件&#xff0c;这里最好用谷歌浏览器 先请大家看看案例国家水质自动综合监管平台 这里我们只…...

erlang的安装-linux

1&#xff1a;解压 tar -zxvf 安装包 2&#xff1a;进入解压的目录执行&#xff1a; ./configure --prefix/usr/local/erlang --with-ssl --enable-threads --enable-smp-support --enable-kernel-poll --enable-hipe --without-javac 3&#xff1a;编译安装&#xff1a; m…...

Android Coil 3默认P3色域图加载/显示不出来

Android Coil 3默认P3色域图加载/显示不出来 解决&#xff0c;需要在Androidmanifest.xml使用Coil 3的activity配置属性&#xff1a; <activityandroid:colorMode"wideColorGamut"...</activity>...

【LaTeX】安装

Register - Overleaf, 在线LaTeX编辑器 注册Overleaf 安装 Latex2022 安装教程&#xff08;附安装资源&#xff09;_tex2022安装教程-CSDN博客 注&#xff1a;先安装 texlive&#xff0c;再安装TexStudio \documentclass{article} % 这里是导言区 \begin{document}Hello, wor…...

【2025年认证杯数学中国数学建模网络挑战赛】A题 解题建模过程与模型代码(基于matlab)

目录 【2025年认证杯数学建模挑战赛】A题解题建模过程与模型代码&#xff08;基于matlab&#xff09;A题 小行星轨迹预测解题思路第一问模型与求解第二问模型与求解 【2025年认证杯数学建模挑战赛】A题 解题建模过程与模型代码&#xff08;基于matlab&#xff09; A题 小行星轨…...

【KWDB 创作者计划】KWDB 数据库全维度解析手册

——从原理到实践&#xff0c;构建下一代数据基础设施 ​第一章&#xff1a;KWDB 设计哲学与技术全景 1.1 为什么需要 KWDB&#xff1f; 在数据爆炸与业务场景碎片化的今天&#xff0c;传统数据库面临三大挑战&#xff1a;​扩展性瓶颈​&#xff08;单机性能天花板&#xff…...

低代码开发能否取代后端?深度剖析与展望-优雅草卓伊凡

低代码开发能否取代后端&#xff1f;深度剖析与展望-优雅草卓伊凡 在科技迅猛发展的当下&#xff0c;软件开发领域新思潮与新技术不断涌现&#xff0c;引发行业内外热烈探讨。近日&#xff0c;笔者收到这样一个颇具争议的问题&#xff1a;“低代码开发能取代后端吗&#xff1f…...

LeetCode hot 100—最长回文子串

题目 给你一个字符串 s&#xff0c;找到 s 中最长的 回文 子串。 示例 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba" 同样是符合题意的答案。示例 2&#xff1a; 输入&#xff1a;s "cb…...

蓝桥杯知识总结

文章目录 1.常用的数学方法2.大小写转换3.数组和集合排序数组排序集合排序 4.控制小数位数5.栈6.队列7.字符串相关方法8.十进制转n进制模板字符转为十进制某进制转化为十进制 9.前缀和10.差分11.离散化12.双指针13.二分14.枚举模板组合型枚举模板排列型枚举模板 15.搜索算法BFS…...

leetcode:2839. 判断通过操作能否让字符串相等 I(python3解法)

难度&#xff1a;简单 给你两个字符串 s1 和 s2 &#xff0c;两个字符串的长度都为 4 &#xff0c;且只包含 小写 英文字母。 你可以对两个字符串中的 任意一个 执行以下操作 任意 次&#xff1a; 选择两个下标 i 和 j 且满足 j - i 2 &#xff0c;然后 交换 这个字符串中两个…...

Python Lambda表达式详解

Python Lambda表达式详解 1. Lambda是什么&#xff1f; Lambda是Python中用于创建匿名函数&#xff08;没有名字的函数&#xff09;的关键字&#xff0c;核心特点是简洁。它适用于需要临时定义简单函数的场景&#xff0c;或直接作为参数传递给高阶函数&#xff08;如map()、f…...

Matlab 平衡车的建模与控制

1、内容简介 Matlab 189-平衡车的建模与控制 可以交流、咨询、答疑 2、内容说明 略 平衡车的建模与控制 选择一款平衡车&#xff08;如&#xff1a;小米九号平衡车等&#xff09;&#xff0c;并估计平衡车的关键参数。完成以下工作&#xff1a; 1. 建立平衡车模型&#xf…...

KWDB创作者计划—KWDB关系库与时序库混搭

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验 Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯…...

Android studio2024的第一个安卓项目

目录 一、创建项目 1、创建Empty Views Activity类型项目 2、Android项目结构解析 manifests 目录&#xff1a; Gradle Scripts目录 3、创建安卓应用 二、测试 1、模拟器测试效果 2、连接真机&#xff0c;然后直接选择真机运行即可&#xff08;点击Run或Shift F10运行…...

航电系统之障碍物监测技术篇

航电系统的障碍物监测技术是保障飞行安全、提升飞行效率的核心技术之一&#xff0c;尤其在复杂环境和低空飞行中发挥着关键作用。以下从技术原理、传感器类型、数据处理与应用等方面进行系统介绍&#xff1a; 一、技术原理 航电系统的障碍物监测技术通过多传感器融合和智能算法…...

网站DDoS防护方案——构建企业级安全屏障的关键路径

本文深度解析DDoS攻击最新演变趋势与防御技术体系&#xff0c;通过攻击特征图谱、云原生防护架构、混合防御模型等维度&#xff0c;揭示企业级网站防护方案的设计逻辑。结合2023年金融行业千万级QPS攻击事件&#xff0c;引用Gartner最新防御技术成熟度曲线&#xff0c;给出可落…...

Linux系统使用lshw生成硬件报告方法

使用 lshw 生成 HTML 硬件报告指南 一、工具简介 lshw(List Hardware)是 Linux 系统下用于检测并报告硬件详细信息的命令行工具,支持输出多种格式(文本、HTML、XML 等)。 核心功能: 显示 CPU、内存、磁盘、PCI/USB 设备等完整硬件信息生成结构化报告,便于存档或分析支…...

力扣 905 按奇偶排序数组:双指针法的优雅实现

目录 问题背景 题目解析 解题思路 暴力解法 双指针法 代码实现 代码解析 算法效率 实际应用场景 总结 问题背景 在编程的世界里&#xff0c;数组排序问题一直是经典中的经典。今天我们要解决的是一个有趣的变种&#xff1a;按奇偶排序数组。题目要求我们将一个整数数…...

LeetCode hot 100—子集

题目 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2…...

BERT - BertTokenizer, BertModel API模型微调

本节代码将展示如何在预训练的BERT模型基础上进行微调&#xff0c;以适应特定的下游任务。 ⭐学习建议直接看文章最后的需复现代码&#xff0c;不懂得地方再回看 微调是自然语言处理中常见的方法&#xff0c;通过在预训练模型的基础上添加额外的层&#xff0c;并在特定任务的…...

通过代码获取接口文档工具

通过代码获取接口文档工具 介绍使用到的技术使用说明核心源码演示截图工具源码 介绍 1.通过前后端代码来生成规格化的接口文档 2.支持拖拽上传或点击选择文件&#xff0c;可以一次选择多个文件或选择文件夹 3.用户选择前后端代码&#xff0c;工具调用GPT解析&#xff0c;得到规…...

不再卡顿!如何根据使用需求挑选合适的电脑内存?

电脑运行内存多大合适&#xff1f;在选购或升级电脑时&#xff0c;除了关注处理器的速度、硬盘的容量之外&#xff0c;内存&#xff08;RAM&#xff09;的大小也是决定电脑性能的一个重要因素。但究竟电脑运行内存多大才合适呢&#xff1f;这篇文章将帮助你理解不同使用场景下适…...

leetcode589 N叉树的前序遍历

前序遍历的顺序是&#xff1a;根节点 -> 子节点1 -> 子节点2 -> ... -> 子节点N 递归&#xff1a; class Solution { private:void traverse(Node* cur, vector<int>& res){if(cur NULL) return;res.push_back(cur->val);for(Node* child: cur->…...

游戏引擎学习第216天

回顾并为当天做准备 你可以看到&#xff0c;游戏现在正在运行。如果我没记错的话&#xff0c;我们之前把调试系统关闭了&#xff0c;留下一个状态&#xff0c;让任何想要在这段时间内进行实验的人可以自由操作&#xff0c;因为我们还没有完全完成这个系统。所以这样做是为了确…...

JavaSE反射机制干货

1.反射(Relection) 理解 定义&#xff1a;程序运行状态,动态地获取程序信息及调用程序功能即为java反射机制 2.获取class对象 掌握 2.1 Java代码的3个阶段 Java代码在计算机中经历的三个阶段:Source源代码阶段-Class类对象阶段-Runt…...

[特殊字符] 第十一讲 | 空间回归模型实战:SAR / SEM / GWR逐个击破

&#x1f4d8; 专栏&#xff1a;科研统计方法实战分享 | 地学/农学人的数据分析工具箱 ✍️ 作者&#xff1a;平常心0715 &#x1f511; 本讲关键词&#xff1a;空间滞后模型&#xff08;SAR&#xff09;、空间误差模型&#xff08;SEM&#xff09;、地理加权回归&#xff08;G…...

AI前沿周报:2025年3月技术深度解析

以下是基于2024-2025年AI技术前沿动态的深度技术周报示例&#xff0c;结合行业最新突破与研究进展&#xff0c;突出技术原理与应用场景分析&#xff1a; AI前沿周报&#xff1a;2025年3月技术深度解析 时间范围&#xff1a;2025年3月1日-3月31日 本期焦点&#xff1a;模型透明…...

aidigu开源微博项目程序,PHP开发的开源微博系统,自媒体个人创业、网盘推广首先

一、软件介绍 文末提供程序和源码下载学习 PHP开发的开源微博系统&#xff0c;采用PHP MySQL开发&#xff0c;框架采用ThinkPHP5.1&#xff0c;用户登录后拥有专属ID&#xff0c;支持表情、关注用户&#xff0c;网盘分享等功能&#xff0c;支持图片上传,视频上传,网盘存储分享…...

Tabnet介绍(Decision Manifolds)和PyTorch TabNet之TabNetRegressor

Tabnet介绍(Decision Manifolds)和PyTorch TabNet之TabNetRegressor Decision ManifoldsTabNet1.核心思想2. 架构组成3. 工作流程4. 优点PyTorch TabNetTabNetRegressor参数1. 模型相关参数`n_d``n_a``n_steps``gamma``cat_idxs``cat_dims``cat_emb_dim`2. 训练相关参数`opti…...

格瑞普Tattu正式成为2025年中国无人机竞速联赛官方赞助商!

格瑞普Tattu正式成为2025年中国无人机竞速联赛官方赞助商! 为飞手赋能&#xff0c;为赛事护航! Tattu是深圳市格瑞普电池有限公司(Grepow)旗下的子品牌之一&#xff0c;专注为无人机、FPV和模型爱好者提供专业可靠的电池和充电器等一站式电源解决方案。凭借卓越的放电性能、稳…...

PySide6 监测设备变更事件

在PySide6中监听系统事件&#xff0c;判断是否有串口设备插拔&#xff0c;进而当串口状态变更时&#xff0c;实现列表数据实时更新。 在Qt中&#xff0c;可以使用 nativeEvent 接口来完成这一操作&#xff1a; [virtual protected] bool QWidget::nativeEvent(const QByteArray…...

嵌入式系统的历史与发展​

目录 引言​ 一、嵌入式系统的早期萌芽​ 1、首个现代嵌入式系统 2、早期未成形嵌入式系统的应用 二、以单片机为主的初级阶段​ 1、工业领域应用 2、大型家电领域应用 三、处理器升级与多样化应用阶段​ 1、数字化电子化设备涌现 &#xff08;1&#xff09;智能仪表…...

mysql调试记录

ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY password; 该命令在调试python使用pymysql连接数据库出现错误时&#xff0c; 报错为pymysql.err.OperationalError: (1045, "Access denied for user rootlocalhost (using password: NO)") m…...

【后端开发】Spring MVC阶段总结

文章目录 快捷引入依赖lombok的使用Lombok依赖Lombok使用Lombok注解 三层架构分层的目的MVC与分层的区别三层架构分层的好处 企业命名规范常见命名命名风格介绍大驼峰风格小驼峰风格包名 常见注解Cookie与Session 快捷引入依赖 这个方法可以快捷引入依赖&#xff0c;但是引入依…...

netty-socketio + springboot 消息推送服务

netty-socketio springboot 消息推送服务 后端1. 目录结构&#xff1a;代码pom文件&#xff1a;application.yml&#xff1a;SocketIOConfig&#xff1a;PushMessage&#xff1a;ISocketIOServiceSocketIOServiceImpl&#xff1a;pushMessageController&#xff1a;启动类&…...

基于 JavaWeb 的 SSM 在线视频教育系统设计和实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

同时打开多个Microchip MPLAB X IDE

0.引用 Microchip 32位MCU CAN驱动图文教程-附源码 - 哔哩哔哩 https://bbs.21ic.com/icview-3391426-1-1.html https://bbs.21ic.com/icview-3393632-1-1.html 1.前言 工作中接触到使用Microchip 的 MPLAB X IDE 开发工具&#xff0c;使用的MCU是Microchip SAMD21J18A MCU…...

dify 500错误

问题 升级到1.2.0 后所有页面接口均报错500, 环境&#xff1a; docker 本地部署 version:1.2.0 解决办法 1.首先关闭服务 docker compose down2.找到docker-compose.yaml里的plugin_daemon&#xff0c;参照下面修改参数 plugin_daemon:environment:PLUGIN_MAX_EXECUTION…...