设计模式——责任链模式
文章目录
- 责任链模式的定义
- 场景示例
- 责任链模式实现方案
- 责任链模式扩展
- 责任链模式的优缺点
- 责任链模式在框架源码中的应用
责任链模式的定义
责任链模式又称职责链模式,是一种行为型设计模式。官方描述:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
原文链接或文中示例代码下载,请关注公众号【Qin的学习营地】,回复:【责任链模式】
场景示例
上述定义是对责任链模式这种思想的归纳总结,理解起来稍微抽象,下面结合一种场景逐步深入责任链模式。
企业采购
在企业中经常需要采购一些物品,小到一些廉价的生活用品,大到昂贵的精密器械,采购金额高低各异,不同采购金额需要由不同领导层次的管理人审批。比如金额在1万以下的只需部门负责人审批即可;金额超过1万且10万以下,部门负责人无权审批,需交由总经理审批;金额超过10万以上则只能层层上报到董事长,由董事长审批了,如下图。
简单的 if…else 实现方案
在上述企业采购中,采购金额不同分别交由不同层次的领导审批,这里最简单的实现方案就是使用 if…else 判断。代码如下:
// 采购审批处理类
public class PurchaseHandler {// 采购审批处理方法public String handleRequest(String purchaserName, Double purchaseAmount){if (purchaseAmount < 10000.0){ // 部门负责人审批return approvalByDepartmentLeader(purchaserName, purchaseAmount);} else if (purchaseAmount < 100000.0) { // 总经理审批return approvalByManager(purchaserName, purchaseAmount);} else { // 董事长审批return approvalByChairman(purchaserName, purchaseAmount);}}private String approvalByDepartmentLeader(String purchaserName, Double purchaseAmount){return (purchaserName + "申请采购金额:" + purchaseAmount + "元, 审批人:部门负责人");}private String approvalByManager(String purchaserName, Double purchaseAmount){return (purchaserName + "申请采购金额:" + purchaseAmount + "元, 审批人:总经理");}private String approvalByChairman(String purchaserName, Double purchaseAmount){return (purchaserName + "申请采购金额:" + purchaseAmount + "元, 审批人:董事长");}
}
if…else 实现方案存在的问题
分析 if…else 实现方案存在的问题:
- 代码结构不够清晰干净。
- 采购审批中的每个审批环节可能存在业务逻辑改动,比如部门负责人审核完之后,还是总经理签字,这就需要修改审批处理类和方法。
- 采购审批流程发生变化,当金额超过一定数额时,也不能完全由董事长审批,需要通过董事会投票决定,这就需要增加一个审批步骤,同样也需要修改源代码。
责任链模式实现方案
仔细分析上面的场景,客户端提出一个采购申请请求,对于客户端来说,他不需要关心是谁审批,后续审批流上可能是由部门负责人、总经理、董事长任一符合方进行审批。这样从部门负责人到总经理、再到董事长审批流程,可以看作是一条链,客户端提出的申请请求在这个链上传递,直到对应的责任人审批为止。
流程中可能在任意位置新增环节,每个环节可能会修改自己的处理逻辑,为了方便修改或复用每个环节;或者扩展新增环节,组合不同流程,可以将每个环节作为一个单独的对象,并且只实现单一的处理功能,这样细粒度划分功能,有利于降低修改的影响面和提高扩展性。
责任链模式概念
责任链模式就体现了上述细粒度抽取的思想,核心在于引入了一个抽象处理者。
责任链模式结构图:
责任链模式中的角色:
-
Handler(抽象处理者):一个处理请求的接口,一般设计为抽象类,其中定义一个处理请求的抽象方法,不同的具体处理者实现该方法;每个处理者可能需要将请求传递给下一个处理者,所以还可以定义一个处理者对象,作为后继者的引用,从而实现一条链。
-
ConcreteHandler(具体处理者):抽象处理者的具体实现子类,实现抽象处理类中的抽象方法,方法需要实现的两个功能:一是处理请求,处理具体处理者职责范围内的请求;二是转发请求,不在该具体处理者职责范围内的请求,就将请求转发给后继者处理。
-
Client(客户端):责任链客户端,组合处理者对象构造责任链,同时请求责任链处理请求对象。
组合的顺序很重要,如果顺序不对,处理的结果可能就不是符合要求的。
Client 不算责任链中的角色,外部使用责任链模式时自行创建。
责任链模式代码示例:
1、定义抽象处理者接口类,类中持有下一个处理者对象,同时实现请求处理方法:
// 定义责任链抽象接口类
public abstract class Handler {// 持有下一个处理者对象引用protected Handler nextHandler;// 设置下一个处理者对象public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}// 处理采购申请请求public abstract String handleRequest(String purchaserName, Double purchaseAmount);
}
2、实现具体处理者类,实现处理请求的具体方法,方法内部逻辑:处理请求的具体逻辑,或者将请求对象传递给下一个处理者。这里实现三个具体处理者。
-
DepartmentLeaderHandler 部门负责人处理类
// 部门负责人处理类 public class DepartmentLeaderHandler extends Handler {@Overridepublic String handleRequest(String purchaserName, Double purchaseAmount) {// 职责范围内处理审批请求if (purchaseAmount < 10000){return (purchaserName + "申请采购金额:" + purchaseAmount + "元, 审批人:部门负责人");} else {// 职责范围外处理,交由下一个处理者处理if (this.nextHandler != null){return this.nextHandler.handleRequest(purchaserName, purchaseAmount);}}return null;} }
-
ManagerHandler 总经理处理类
// 总经理处理类 public class ManagerHandler extends Handler {@Overridepublic String handleRequest(String purchaserName, Double purchaseAmount) {// 职责范围内处理审批请求if (purchaseAmount < 100000){return (purchaserName + "申请采购金额:" + purchaseAmount + "元, 审批人:总经理");} else {// 职责范围外处理,交由下一个处理者处理if (this.nextHandler != null){return this.nextHandler.handleRequest(purchaserName, purchaseAmount);}}return null;} }
-
ChairmanHandler 董事长处理类
// 董事长处理类 public class ChairmanHandler extends Handler {@Overridepublic String handleRequest(String purchaserName, Double purchaseAmount) {// 职责范围内处理审批请求if (purchaseAmount >= 100000){return (purchaserName + "申请采购金额:" + purchaseAmount + "元, 审批人:董事长");} else {// 职责范围外处理,交由下一个处理者处理if (this.nextHandler != null){return this.nextHandler.handleRequest(purchaserName, purchaseAmount);}}return null;} }
3、客户端组合处理者构建责任链并调用
public class Client {public static void main(String[] args) {// 创建责任链上的每个处理者对象DepartmentLeaderHandler departmentLeaderHandler = new DepartmentLeaderHandler();ManagerHandler managerHandler = new ManagerHandler();ChairmanHandler chairmanHandler = new ChairmanHandler();// 组合处理者对象构造责任链departmentLeaderHandler.setNextHandler(managerHandler);managerHandler.setNextHandler(chairmanHandler);// 提交请求,调用责任链,调用责任链第一个处理者对象即可String result = departmentLeaderHandler.handleRequest("采购人员", 105000.0);System.out.println(result);}
}
当调用责任链处理请求时,并不知道谁会真正处理请求,只知道将请求提交到第一个处理者对象。从第一个处理者对象开始,整个责任链中的对象,要么自己处理请求,要么继续转发给下一个接收者。
从 if…else 判断到责任链模式的使用可以看出,代码结构变得清晰了。 责任链模式很好的满足了单一职责和开闭原则。
在责任链模式中,可能没有合适的处理者,请求不一定会被处理,所以可以在最后加上不支持处理该请求的提示。
责任链模式扩展
责任链构建方式
责任链构建方式多种多样,现在总结三种基本的实现方式:
1、客户端在提交请求前组合处理者构造责任链,即在使用的时候动态组合链。如前面责任链的实现就是这种。
2、可以在抽象处理者 Handler 内部实现责任链的组合。
3、由各个具体处理者自己决定后继者,这种方式要求每个处理者了解业务流程。
纯与不纯的责任链
纯的责任链模式
- 纯的责任链模式的每个处理者对象只会做两件事,要么处理请求并返回,要么将请求传递给链上的下一个处理者对象。
不纯的责任链模式
- 不满足纯的责任链模式要求的就是不纯的责任链,也可以称为功能链。一个请求在责任链中传递,每个处理者对象负责处理请求的某一方面的功能,处理完成后,不是停止,而是继续向后继者传递请求,后继者可以继续处理该请求。
- 在实际应用开发中,进行业务处理之前,通常需要进行权限检查、通用数据校验、数据逻辑校验等处理,然后才开始真正的业务逻辑实现。可以把这些功能分散到一个功能链中。这样做的目的是使程序结构更加灵活,而且复用性会更好。比如通用的权限检查只需要做一份,然后就可以在多个功能链中使用了。
责任链模式的优缺点
优点:
-
请求者和处理者松散耦合
在责任链模式中,请求者并不知道接收者是谁,也不知道具体如何处理,请求者只是负责向责任链发出请求就可以了。而每个处理者对象也不用管请求者或者是其他的处理者对象,只负责处理自己的部分,其他的就交给其他的处理者对象去处理。并且链中的对象不需要知道链的结构,可以由客户端负责链的创建,降低耦合。
-
动态组合
责任链模式会把功能处理分散到单独的处理者对象中,然后在使用的时候,可以动态组合处理者形构造责任链,从而可以灵活地给对象分配职责,也可以灵活地实现和改变对象的职责。
-
符合开闭原则
在系统中新增具体处理者对象时无需修改原代码,只需要在客户端重新构建责任链即可。
缺点:
-
产生很多细粒度对象
责任链模式会把功能处理分散到单独的处理者对象中,也就是每个处理者对象只处理一个方面的功能,要把整个业务处理完,需要很多处理者对象的组合,这样会产生大量的细粒度处理者对象。
-
不一定能被处理
责任链模式的每个处理者对象只负责自己处理的那一部分,因此可能会出现某个请求,把整个链传递完了,都没有处理者对象处理它。这就需要在使用责任链模式的时候,需要提供默认的处理,并且注意构建的链的有效性。
-
责任链模式可能会带来一些额外的性能损耗,因为它每次执行请求都要从链子开头开始遍历。甚至责任链构建不当,出现循环调用,导致系统陷入死循环。
责任链模式在框架源码中的应用
完整后续内容请关注公众号【Qin的学习营地】,回复:【责任链模式】
相关文章:
设计模式——责任链模式
文章目录 责任链模式的定义场景示例责任链模式实现方案责任链模式扩展责任链模式的优缺点责任链模式在框架源码中的应用 责任链模式的定义 责任链模式又称职责链模式,是一种行为型设计模式。官方描述:使多个对象都有机会处理请求,从而避免请…...
nginx得if语句内proxy_pass不允许携带url部分,如何处理
在nginx中,proxy_pass指令不能直接携带URL部分。但是,可以使用rewrite指令结合正则表达式来处理URL部分。 下面是一个示例配置,演示如何使用rewrite指令将URL中的某个部分进行替换后传递给后端服务器: location /v100/{proxy_…...
CentOS7设置 redis 开机自启动
CentOS7设置 redis 开机自启动 步骤1.创建redis.service文件2.重新加载所有服务3.设置开机自启动4.自由地使用linux系统命令4.1.启动 Redis 服务4.2.查看 Redis 状态(-l:查看完整的信息)4.3.停止 Redis 服务4.4.重启 Redis 服务 步骤 如果你傲娇,不想拷贝࿰…...
C++虚函数(定义,作用,原理,案例)
一.定义: C的虚函数是在父类(基类)中声明的的函数,它可在子类(派生类)中重写。二.作用 虚函数的目的是实现多态性,即在程序运行时根据对象的实际类型确定调用哪个函数。三.使用方法: 在基类中声明虚函数时,需要在函…...
C#中.NET 6.0 控制台应用通过EF访问新建数据库
目录 一、 操作步骤 二、编写EF模型和数据库上下文 三、 移植(Migrations)数据库 四、编写应用程序并运行 前文已经说过.NET Framework4.8 控制台应用通过EF访问新建数据库,这里的数据据库要根据事先编写好的EF模型、经过一番操作&#x…...
conda创建pytorch环境报错
昨天训练数据的时候,发现Anaconda占用C盘达到了20G(暑假在cmd状态下安装的,默认下载到了C盘),心道再创建几个环境,C盘就要爆红了,于是重装Anaconda到了D盘,不过之后的初始化并不顺利…...
数据结构-插入排序实现
文章目录 1、描述2、代码实现3、结果4、复杂度 1、描述 待排序的数组分为已排序、未排序两部分; 初始状态时,仅有第一个元素为已排序序列,第一个以外的元素为未排序序列; 此后遍历未排序序列, 将元素逐一插入到已排序的序列中&am…...
CGlib动态代理和JDK动态代理
CGlib代理模式是一种基于字节码操作的代理模式,它通过生成被代理类的子类来实现代理功能。 CGlib通过继承被代理类,生成一个代理类的子类,并重写父类的方法,在方法的前后插入相应的代理逻辑。这种方式不需要被代理类实现接口&…...
分类预测 | Matlab实现PSO-GRU-Attention粒子群算法优化门控循环单元融合注意力机制多特征分类预测
分类预测 | Matlab实现PSO-GRU-Attention粒子群算法优化门控循环单元融合注意力机制多特征分类预测 目录 分类预测 | Matlab实现PSO-GRU-Attention粒子群算法优化门控循环单元融合注意力机制多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现PSO…...
Python OpenCV 视频抽帧处理并保存
上篇文章中基于OpenCV实现图像处理后,类似的,也可以对视频进行处理。OpenCV库可以将视频的每一帧读取出来,然后对每一帧图像做相应的操作,并保存成新的视频。 1. 读取视频,获取相关参数 import cv2 import numpy as…...
英伟达AI布局的新动向:H200 GPU开启生成式AI的新纪元
英伟达Nvidia是全球领先的AI计算平台和GPU制造商,近年来一直在不断推出创新的AI产品和解决方案,为各行各业的AI应用提供强大的支持。 最近,英伟达在GTC 2023大会上发布了一款专为训练和部署生成式AI模型的图形处理单元(GPU&#…...
Windows11 python3.12 安装pyqt6 pyqt6-tools
Windows11 python3.12 安装pyqt6比较容易,但pyqt6-tools一直安装不上去。出错信息如下: (venv) PS D:\python_project\pyqt6> pip install pyqt6-tools Collecting pyqt6-toolsUsing cached pyqt6_tools-6.4.2.3.3-py3-none-any.whl (29 kB) Collec…...
反弹Shell
概述 反弹shell(reverse shell)就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与telnet,ssh等标准shell对应,本质上是网络概念的客户端与服务端…...
Guava RateLimiter的限流机制详解
限流是保护高并发系统的三种有效方法之一。另外两个分别是缓存和降级。限流在很多场景中都会使用到限制并发数和请求数。例如,在限时抢购的情况下,限流可以保护您自己的系统和下游系统不被巨大的流量淹没。 限流的目的是通过限制并发访问或请求或者限制…...
详解nginx的root与alias
在Nginx中,root和alias指令都可以用来指定Web服务器中的文件根目录。不过,它们之间有一些关键的区别。 root指令指定的是服务器根目录,是用于处理HTTP请求时所使用的默认根目录。例如,若root /var/www/html;,则访问htt…...
在HBuilderX中配置Vue Router的步骤
以下是在HBuilderX中配置Vue Router的步骤: 在项目中安装Vue Router,可以使用npm或yarn命令进行安装。 在src目录下创建routers.js文件,并在该文件中编写路由相关代码,例如: import Vue from vue import Router from …...
通过接口抓取公众号信息并群发
总体步骤 通过非官方接口,登陆公众号获取cookie、token通过token拼接需要的参数,请求被抓取的公众号列表数据通过列表数据获取文章内容解析文章内容并通过官方接口创建草稿通过非官方接口群发创建的草稿(非认证用户,已认证用户可以通过官方接…...
Python基础入门----如何通过conda搭建Python开发环境
文章目录 使用 conda 搭建Python开发环境是非常方便的,它可以帮助你管理Python版本、依赖库、虚拟环境等。以下是一个简单的步骤,演示如何通过 conda 搭建Python开发环境: 安装conda: 如果你还没有安装 conda,首先需要安装Anaconda或Miniconda。Anaconda是一个包含很多数据…...
计算机网络的体系结构
目录 一. 计算机体系结构的形成二. 协议与层次划分2.1 数据传输过程2.2 什么是网络协议2.3 网络协议的三要素2.4 协议有两种形式2.4 各层协议2.5 什么是复用和分用 \quad 一. 计算机体系结构的形成 \quad 计算机网络是一个非常复杂的系统, 相互通信的两个计算机系统必须高度协调…...
cesium雷达扫描(模糊圆效果)
cesium雷达扫描(模糊圆效果) 1、实现思路 使用ellipse方法加载圆型,修改ellipse中‘material’方法重写自己的glsl来实现当前效果 1、示例源码 index.html <!DOCTYPE html> <html lang="en"><head><!<...
windows安装wsl2以及ubuntu
查看自己系统的版本 必须运行 Windows 10 版本 2004 及更高版本(内部版本 19041 及更高版本)或 Windows 11 才能使用以下命令 在设置,系统里面就能看到 开启windows功能 直接winQ搜 开启hyber-V、使用于Linux的Windows子系统、虚拟机平…...
音视频项目—基于FFmpeg和SDL的音视频播放器解析(十二)
介绍 在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器 如果您不理解本…...
键鼠自动化2.0树形结构讲解
介绍 在键鼠自动化2.0中使用Qtc实现了全自定义树形结构,实现任务的拖拽,复制粘贴,撤销重做,以及包括树形结构增加序号展示,以及增加搜索功能 实现 1.自定义节点 // 自定义节点类 class TreeNode : public QObject …...
2023年【金属非金属矿山安全检查(地下矿山)】考试报名及金属非金属矿山安全检查(地下矿山)最新解析
题库来源:安全生产模拟考试一点通公众号小程序 金属非金属矿山安全检查(地下矿山)考试报名参考答案及金属非金属矿山安全检查(地下矿山)考试试题解析是安全生产模拟考试一点通题库老师及金属非金属矿山安全检查&#…...
Java 12 及Tomcat 部署配置
使用的软件版本 1. Java12部署 和之前的Java版本不太一样,12版本不用配置JRE环境。 解压缩文件夹 root账户执行 tar -xzvf /home/software/jdk-12.0.2_linux-x64_bin.tar.gz创建java文件夹 root账户执行 cd /usr mkdir java移动Java文件到创建的文件夹下 root账…...
pandas教程:Date Ranges, Frequencies, and Shifting 日期范围,频度,和位移
文章目录 11.3 Date Ranges, Frequencies, and Shifting(日期范围,频度,和位移)1 Generating Date Ranges(生成日期范围)2 Frequencies and Date Offsets(频度和日期偏移)Week of mo…...
设计模式 - 概览
一、概念 分为三大类、23中具体设计模式。 类型原理具体模式创建型封装了具体类的信息,隐藏了类的实例化过程。 单例模式(Singleton) 工厂方法模式(Factory Method) 抽象工厂模式(Abstract Factory…...
【Linux】Makefile
一、gcc 的缺点 gcc -o test a.c b.c我们具体分析:gcc -o test a.c b.c这条命令 它们要经过下面几个步骤: 1)对于a.c:执行:预处理 编译 汇编 的过程,a.c >xxx.s >xxx.o 文件。2)对于b.c…...
TS的函数如何定义类型
如何接受arguments参数 function add(...args: string[]) {let list4: IArguments arguments;}add(1, 2) 自定义一个args interface A1 {callee: Function,length: number,[index: number]: any}function adds(...args: string[]) {let list4: A1 arguments;}adds(1, 2) …...
xstream实现xml和java bean 互相转换
目录 pom引用java bean 类XML 转换工具类测试类执行结果注意问题 JAXB方式见: JAXB实现XML和Bean相互转换 Java中实现XML和Bean的转换的方式或插件有以下几种: JAXB(Java Architecture for XML Binding):JAXB是Java …...
斯坦福机器学习 Lecture1 (机器学习,监督学习、回归问题、分类问题定义)
https://www.bilibili.com/video/BV1JE411w7Ub?p1&vd_source7a1a0bc74158c6993c7355c5490fc600 笔记如下 机器学习的定义:不需要明确编程就能让计算机去学习做某件事情 另一个定义 什么是监督学习? 给定一组 (x,y) 样本,学习一个 x-&g…...
五、Linux目录结构
1.基本介绍 1.Linux的文件系统是采用级层式的树状目录结构,在此结构中的最上层是根目录"r/",然后在此目录下再创建其他的目录。 2.深刻理解linux树状文件目录是非常重要的 3.记住一句经典的话:在Linux世界里,一切皆文件…...
C/C++数据结构之中缀表达式转换为后缀表达式,删除堆栈元素
在这篇博客中,我们将深入分析一个使用C编写的栈和表达式计算程序。该程序不仅实现了基本的栈操作,还提供了中缀表达式转后缀表达式和删除堆栈中的元素等实用功能。通过逐一讲解每个函数的功能,我们将更全面地理解这个程序的实现。 资源获取&a…...
uni-app下,页面跳转后wacth持续监听的问题处理
uni-app下,页面跳转后wacth持续监听的问题处理 好久没写博客了,最近碰到了一个uni-app(vue2)开发小程序的问题,个人觉得很典型,所以拿出来给各位做个参考。 需求场景: 全局轮询用户权限。简单…...
Python技术栈 —— 语言基础
Python基础 语法拾遗List与Tuple的区别yield关键字for in enumeratefor in zip 精彩片段测量程序用时 语法拾遗 List与Tuple的区别 ListTuple建立后是否可变可变不可变建立后是否可添加元素可添加不可添加 # list and tuple List [1, 2, 3, 4, 5] Tuple (1, 2, 3, 4, 5) p…...
redis cluster搭建
k8s部署 Redis Insight k8s部署redis集群_mob6454cc6c6291的技术博客_51CTO博客 占用的内存竟然这么小,才200M左右 随便选个节点进去,看能否连接上其他节点 redis-cli -h redis-cluster-v1-0.redis-cluster.project-gulimall.svc.cluster.local 再创建个…...
windows 11 本地运行ER-NeRF及pytorch3D安装
ER-NeRF本地运行只要梳理好依赖版本,运行起来就很顺畅 conda create -n ernerf python3.10 创建本项目虚拟环境conda install pytorch1.12.1 torchvision0.13.1 cudatoolkit11.3 -c pytorch 若windows有多个版本的cuda,需要在环境变量中切换至cuda 11.3&…...
mysql客户端navicat的一些错误合集
关于mysql的客户端的使用的一些问题 问题描述: 在使用navicat prenium客户端的时候,连接数据库出现 Table ‘performance_schema.session_variables’ doesn’t exist 错误 解决方案: 首先找到mysql的bin目录 然后winR 进入到cmd界面 输入…...
【力扣面试经典150题】(链表)K 个一组翻转链表
题目描述 力扣原文链接 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 你不能只…...
数据结构刷题
空间复杂度:临时开辟的空间、空间是可以重复利用的 递归为O(n) 时间复杂度:程序执行次数 消失的数字 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 思路1:利用连续的特点求等差和然后减去所有元素得到的就是消…...
【Android】设置全局标题栏
序言 在做项目的时候,有时候需要一个全局统一的标题栏,保证项目风格的统一,但是如果在每个activity上面都写一遍这个标题栏就很麻烦了,我们经常用的方法就是写个基类Activity,然后当某个Activity需要这个统一的标题栏…...
R语言的入门学习
目录 准备工作导入csv数据集选择前200行作为数据集展示数据集的前/后几N行宏观分析删除缺失值构建直方图导出为图片 R语言常见图像类型例1:散点图例2:散点矩阵图 准备工作 安装教程: R语言和RStudio的下载安装(非常简便舒适&…...
【开源】基于Vue和SpringBoot的民宿预定管理系统
项目编号: S 058 ,文末获取源码。 \color{red}{项目编号:S058,文末获取源码。} 项目编号:S058,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用例设计2.2 功能设计2.2.1 租客角色…...
nacos集群部署
GitHub - nacos-group/nacos-k8s: This project contains a Nacos Docker image meant to facilitate the deployment of Nacos on Kubernetes using StatefulSets. 需要修改两个文件 --- apiVersion: v1 kind: Service metadata:name: nacos-headlessnamespace: project-guli…...
9、传统计算机视觉 —— 边缘检测
本节介绍一种利用传统计算机视觉方法来实现图片边缘检测的方法。 什么是边缘检测? 边缘检测是通过一些算法来识别图像中物体之间,或者物体与背景之间的边界,也就是边缘。 边缘通常是图像中灰度变化显著的地方,标志着不同区域的分界线。 在一张图像中,边缘可以是物体的…...
Linux tc 使用
tc模拟延时丢包等网络故障依赖的内核驱动 /lib/modules/5.15.0-52-generic/kernel/net/sched/sch_netem.ko有些系统并不是默认就安装上该驱动的,如果没有安装该驱动,构造网络故障时会报错。 root:curtis# tc qdisc change dev enp4s0 root netem delay…...
从0开始学习JavaScript--JavaScript 数字与日期
JavaScript中的数字和日期是处理数值计算和时间相关任务的核心。本文将深入研究JavaScript中数字的表示、常见运算,以及日期对象的创建、格式化等操作,并通过丰富的示例代码,可以更全面地了解和应用这些概念。 JavaScript数字基础 JavaScri…...
从关键新闻和最新技术看AI行业发展(2023.11.6-11.19第十期) |【WeThinkIn老实人报】
Rocky Ding 公众号:WeThinkIn 写在前面 【WeThinkIn老实人报】旨在整理&挖掘AI行业的关键新闻和最新技术,同时Rocky会对这些关键信息进行解读,力求让读者们能从容跟随AI科技潮流。也欢迎大家提出宝贵的优化建议,一起交流学习&…...
计算机硬件的基本组成
一、冯诺依曼结构 存储程序: “存储程序”的概念是指将指令以二进制代码的形式事先输入计算机的主存储器,然后按其在存储器中的首地址执行程序的第一条指令,以后就按该程序的规定顺序执行其他指令,直至程序执行结束。 冯诺依曼计…...
【算法-哈希表3】四数相加2 和 赎金信
今天,带来哈希表相关算法的讲解。文中不足错漏之处望请斧正! 理论基础点这里 1. 四数相加2 分析题意 求符合条件的四元组的出现次数,条件: nums1nums2nums3nums4 从四个数组中的每一个数组取一个数 num1, num2, num3, num4&am…...