基于常用设计模式的业务框架
前言
做开发也有好几年时间了,最近总结和梳理自己在工作中遇到的一些问题,工作中最容易写出BUG的需求就是改造需求了。一个成熟的业务系统是需要经过无数次迭代而成的,也意味着经过很多开发人员之手,最后到你这里,大部分时间都是在梳理代码,理解别人的用意。有的业务功能里面一堆IF嵌套嵌套,耦合度太过,理解起来比较费劲,也容易改出BUG。
不同人有不同的编码习惯,这没有办法,但如果系统中能用一些常用的设计模式来编码,那多多少少能增加可读性,降低耦合度,所以想做出几种常用的设计模式工具类,开发时可以直接使用,让我们更加专注于业务代码开发。
正文
框架基于常用的设计模式,策略模式、模板方法模式、工厂模式、责任链模式等,结合Spring IOC,Spring AOP,Springboot自动装配;
Github地址:点击查看
主要有4个通用的设计模式处理器:
通用策略模式处理器
业务场景
购买保险产品的费用计算方法有多种,按日计算、按月计算、按费率表计算。不同产品可选择的计费选项可能不一样,如下:
日计算(01):支持 A产品、B产品
月计算(02):支持 A产品、C产品
费率表计算(03):支持 A产品、B产品、C产品
代码演示
//计算类型String calculateType="01";//产品编号String productNo="A";if(calculateType.equals("01")){if ("A,B".contains(productNo)){//按日计算}}else if(calculateType.equals("02")){if ("A,C".contains(productNo)){//按月计算}}else if(calculateType.equals("03")){if ("A,B,C".contains(productNo)){//按费率表计算}}
上面这种场景如果使用 if…else…处理的话,随着代码不断迭代,其可读性、调整成本会变得越来越大;
下面使用策略模式来演示:
定义处理器,继承策略处理器接口
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;import java.util.Arrays;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/11 20:14* @Wechat:DDOS12345H* 按日计算*/
@BComponent
public class Calculate01Handle extends AbstractBHandle<RequestDto,ResponseDto> {@Overridepublic boolean before(RequestDto requestDto) {return true;}@Overridepublic boolean after(RequestDto requestDto) {return true;}@Overridepublic ResponseDto doExecute(RequestDto requestDto) {System.out.println("按日计算");return null;}@Overridepublic CommonBName getName() {//定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器return new CommonBName<String>("01", Arrays.asList("A","B"));}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;import java.util.Arrays;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/11 20:14* @Wechat:DDOS12345H* 按日计算*/
@BComponent
public class Calculate02Handle extends AbstractBHandle<RequestDto,ResponseDto> {@Overridepublic boolean before(RequestDto requestDto) {return true;}@Overridepublic boolean after(RequestDto requestDto) {return true;}@Overridepublic ResponseDto doExecute(RequestDto requestDto) {System.out.println("按月计算");return null;}@Overridepublic CommonBName getName() {//定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器return new CommonBName<String>("02", Arrays.asList("A","C"));}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;import java.util.Arrays;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/11 20:14* @Wechat:DDOS12345H* 按日计算*/
@BComponent
public class Calculate03Handle extends AbstractBHandle<RequestDto,ResponseDto> {@Overridepublic boolean before(RequestDto requestDto) {return true;}@Overridepublic boolean after(RequestDto requestDto) {return true;}@Overridepublic ResponseDto doExecute(RequestDto requestDto) {System.out.println("按费率表计算");return null;}@Overridepublic CommonBName getName() {//定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器return new CommonBName<String>("03", Arrays.asList("A","B","C"));}
}
定义入参类、出参类;
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {//...
}
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {//...
}
运行用例
import com.zdc.business.business.context.StrategyBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/10 19:21* @Wechat:DDOS12345H*/
public class StartApp {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");StrategyBContext strategyBContext = (StrategyBContext) applicationContext.getBean("strategyBContext");//计算类型String calculateType="01";//产品编号String productNo="A";RequestDto requestDto=new RequestDto();ResponseDto execute = strategyBContext.invoke(calculateType,productNo,requestDto,ResponseDto.class);}
}

通用适配器模式处理器
业务场景
现有公司A和公司B进行投保出单,出完单后需要通知相关人员。
公司A:需要邮件、短信通知投保人;
公司B:需要邮件、短信通知被保人,企信通知业务员;
代码演示
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
@Data
public class RequestDto {//定义请求参数String companyType;}
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {//定义相应参数
}
定义A公司适配器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import com.zdc.business.business.handle.adapter.AbstractHandlesAdapter;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:46* @Wechat:DDOS12345H*/
@BComponent
public class NotifyCompanyA extends AbstractHandlesAdapter<RequestDto, ResponseDto> {@Overridepublic boolean isSupport(RequestDto context) {//该方法用于编写适配条件if (context.getCompanyType().equals("A")){return true;}return false;}@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("发邮件通知投保人");System.out.println("发短信通知投保人");return null;}@Overridepublic IAdapterEnumBFactory getType() {//定义该适配器归属类型return ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY;}
}
定义枚举参数
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import lombok.AllArgsConstructor;
import lombok.Getter;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 22:30* @Wechat:DDOS12345H*/
@Getter
@AllArgsConstructorpublic enum ChannelIAdapterEnumBFactory implements IAdapterEnumBFactory {CHANNEL_NOTIFY("notify",10,"公司消息通知处理器"),;String type;int priorityOrder;String description;
}
定义B公司通知适配器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import com.zdc.business.business.handle.adapter.AbstractHandlesAdapter;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:46* @Wechat:DDOS12345H*/
@BComponent
public class NotifyCompanyB extends AbstractHandlesAdapter<RequestDto, ResponseDto> {@Overridepublic boolean isSupport(RequestDto context) {//该方法用于编写适配条件if (context.getCompanyType().equals("B")){return true;}return false;}@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("发邮件通知投保人");System.out.println("发短信通知投保人");System.out.println("企信通知业务员");return null;}@Overridepublic IAdapterEnumBFactory getType() {//定义该适配器归属类型return ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY;}
}
入口代码
import com.zdc.business.business.context.AdapterBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 21:15* @Wechat:DDOS12345H*/
public class StratApp {public static void main(String[] args) {//SpringBoot环境下可直接使用@AutowireAnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");AdapterBContext adapterBContext = (AdapterBContext) applicationContext.getBean("adapterBContext");//假设当前是A公司投保RequestDto requestDto=new RequestDto();requestDto.setCompanyType("A");ResponseDto execute = adapterBContext.execute(ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY.type, requestDto, ResponseDto.class);}
}

通用责任链模式处理器
业务场景
在录单系统中,录单员填写完资料,通常下一步需要提交审核,而在正式提交审核之前,系统需要校验数据是否符合要求。某些场景下不想完全卡主流程,通常会以软提示的方式在前端进行提醒;现有以下4种软提示校验(从上到下校验顺序):

为了提高体验,当系统抛出资料A校验后,录单员点击“是”进行重新提交,此时由于前面已经点击了“是”了,此时后端不应该再对点击”是“的校验器进行校验。通常这种需要给每个校验器都设置一个标识,当为“是”时,后端跳过校验,但如果校验场景较多时,那代码将难以维护。
现使用责任链模式来处理以上场景
代码演示
定义好请求参数类和相应参数类
import lombok.AllArgsConstructor;
import lombok.Data;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
@Data
@AllArgsConstructor
public class RequestDto {String data;
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {
}
import com.zdc.business.business.factory.IChainsEnumBFactory;
import lombok.AllArgsConstructor;
import lombok.Getter;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:04* @Wechat:DDOS12345H*/
@Getter
@AllArgsConstructor
public enum OrderCheckEnumBFactory implements IChainsEnumBFactory {ORDER_CHECK_SOFT_A("order","checkA",0,"资料A校验器"),ORDER_CHECK_SOFT_B("order","checkB",1,"资料B校验器"),ORDER_CHECK_SOFT_C("order","checkC",2,"资料C校验器"),;//处理器类型,标记所属链String type;//处理器名称String name;//优先级顺序int priorityOrder;//描述String description;
}
自定义异常类
import lombok.AllArgsConstructor;
import lombok.Data;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:12* @Wechat:DDOS12345H*/
@AllArgsConstructor
@Data
public class SoftTipException extends RuntimeException{private String code;private String desc;}
定义校验器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:02* @Wechat:DDOS12345H*/
@BComponent
public class CheckAHandle extends AbstractChainHandle<RequestDto,ResponseDto> {@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("校验器A");if (context.equals("A")){//抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料A可能存在风险,是否继续提交?");}else{//调用下个节点校验器executeNextNode(context);}return null;}@Overridepublic IChainsEnumBFactory getType() {return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_A;}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:02* @Wechat:DDOS12345H*/
@BComponent
public class CheckBHandle extends AbstractChainHandle<RequestDto,ResponseDto> {@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("校验器B");if (context.equals("B")){//抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料B可能存在风险,是否继续提交?");}else{//调用下个节点校验器executeNextNode(context);}return null;}@Overridepublic IChainsEnumBFactory getType() {return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_B;}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:02* @Wechat:DDOS12345H*/
@BComponent
public class CheckCHandle extends AbstractChainHandle<RequestDto,ResponseDto> {@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("校验器C");if (context.equals("C")){//抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料C可能存在风险,是否继续提交?");}else{//调用下个节点校验器executeNextNode(context);}return null;}@Overridepublic IChainsEnumBFactory getType() {return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_C;}
}
运行用例
import com.zdc.business.business.context.ChainsBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/10 19:21* @Wechat:DDOS12345H*/
public class StartApp {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");ChainsBContext chainsBContext = (ChainsBContext) applicationContext.getBean("chainsBContext");//校验标识String checkFlag="checkB";if (!"succeed".equals(checkFlag)){if ("start".equals(checkFlag)){chainsBContext.start("order",new RequestDto(checkFlag),null);}chainsBContext.execute("order",checkFlag,new RequestDto(checkFlag),null);}}
}

通用代理模式处理器
业务场景
与其它周边系统进行交互时,需要将请求报文和响应报文记录到ES中,方便后续排查,并对请求报文加密加签名,响应报文解密验签;
考虑到复用性等方面,所以这里使用代理模式来增强方法最合适不过了。
代码演示
定义ES日志记录增强器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.proxy.AbstractBEnhanceIntecepter;
import com.zdc.business.business.wrapper.IntecepterProceedWrapper;/*** @Author:猪大肠* @Package:com.example.btest.aop* @Date:2023/5/11 22:58* @Wechat:DDOS12345H*/
@BComponent
public class EnhanceEsHandle extends AbstractBEnhanceIntecepter {@Overridepublic Object execute(IntecepterProceedWrapper ipw) {//方法参数Object[] args = ipw.getArgs();System.out.println("请求参数:"+args[0].toString());//调用真正的执行方法Object result = ipw.proceed();System.out.println("响应参数:"+args[0].toString());return result;}
}
加解密增强器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.proxy.AbstractBEnhanceIntecepter;
import com.zdc.business.business.wrapper.IntecepterProceedWrapper;/*** @Author:猪大肠* @Package:com.example.btest.aop* @Date:2023/5/11 22:58* @Wechat:DDOS12345H*/
@BComponent
public class EnhanceEncryHandle extends AbstractBEnhanceIntecepter {@Overridepublic Object execute(IntecepterProceedWrapper ipw) {//方法参数Object[] args = ipw.getArgs();System.out.println("对请求报文加密:");System.out.println("对请求报文加签:");//调用真正的执行方法Object result = ipw.proceed();System.out.println("对请求报文解密:");System.out.println("对请求报文验签:");return result;}
}
被增强类
import com.zdc.business.business.annotation.InterceptorEnhance;
import org.springframework.stereotype.Component;/*** @Author:猪大肠* @Package:com.example.btest.aop* @Date:2023/5/11 23:06* @Wechat:DDOS12345H*/
@Component
public class HttpToCompanyA {//按顺利指定增强器@InterceptorEnhance(intecepter = {EnhanceEsHandle.class,EnhanceEncryHandle.class})public String sendInfo(String request){return "{code:\"0\",text:\"成功\"}";}}
运行用例

依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>//打包到本地仓库后,引入使用<dependency><groupId>com.zdc.business</groupId><artifactId>business</artifactId><version>0.0.1</version></dependency></dependencies>
总结
本人3年多开发经验,对于各方面认识有限。欢迎老师们指出改进之处,有好的建议或者有想法大家可以交流探讨,一起完善。
相关文章:
基于常用设计模式的业务框架
前言 做开发也有好几年时间了,最近总结和梳理自己在工作中遇到的一些问题,工作中最容易写出BUG的需求就是改造需求了。一个成熟的业务系统是需要经过无数次迭代而成的,也意味着经过很多开发人员之手,最后到你这里,大部…...
ubuntu重启ssh服务
一、开启ssh服务首先需要安装打开ssh服务的库: sudo apt-get install openssh-server 二、检查当前的ssh开启情况: ps -e |grep ssh 三、如果有sshd,则ssh-server已经启动;若仅有agent,则尚未启动; 开启ssh…...
【19】SCI易中期刊推荐——计算机 | 人工智能领域(中科院2区)
💖💖>>>加勒比海带,QQ2479200884<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉…...
Vue.js条件、循环语句
文章目录 条件语句v-ifv-elsev-else-ifv-show 循环语句v-for 指令v-for 迭代对象valuevalue ,keyvalue ,key,index v-for 迭代整数 条件语句 v-if 在元素 和 template 中使用 v-if 指令 <div id"app"><p v-if"seen">现在你看到我…...
Go语言学习查缺补漏ing Day4
Go语言学习查缺补漏ing Day4 一、掌握iota的使用 请看下面这段代码: package mainimport "fmt"const (a iota_bc "ReganYue"dd1e iotaf iota )func main() {fmt.Println(a, b, c, d, d1, e, f) }思考一下输出结果会是什么? …...
说服审稿人,只需牢记这 8 大返修套路!
本文作者:雁门飞雪 如果说科研是一场修炼,那么学术界就是江湖,投稿就是作者与审稿人或编辑之间的高手博弈。 在这一轮轮的对决中,有时靠的是实力,有时靠的是技巧,然而只有实力和技巧双加持的作者才能长久立…...
Java 责任链模式详解
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它用于将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求。在责任链模式中,有一个请求处理链条,每个处理请求的对象都是一个…...
使用MASA全家桶从零开始搭建IoT平台(三)管理设备的连接状态
文章目录 前言分析方案1:遗嘱消息演示遗嘱消息的使用实施流程 方案2:使用WebHook开启WebHook演示Webhook编写代码 前言 获取一个设备的在线和离线状态,是一个很关键的功能。我们对设备下发的控制指令,设备处于在线状态才能及时给我们反馈。这里的在线和…...
我的新书上架了!
talk is cheap,show you my book! 新书《从0开始学ARM》终于在各大平台上架了!! 一、关于本书 1. 本书主要内容 ARM体系架构是目前市面上的主流处理器体系架构,在手机芯片和嵌入式芯片领域,ARM体系架构…...
语言与专业的奇迹:如何利用ChatGPT优化跨国贸易
贸易公司,在进行跨国贸易时,往往需要面对不同国家的甲方或者乙方,在与之沟通的过程中,语言和专业是必须要过的一关,顺畅的交流,往往会带来更好的收益。 今天以“茶”为例,给大家介绍一“知否AI…...
云服务器安装宝塔Linux面板命令脚本大全
阿里云服务器安装宝塔Linux面板,操作系统不同安装命令脚本也不同,支持CentOS、Alibaba Cloud Linux、Ubuntu/Deepin等Linux系统,阿里云服务器网分享阿里云服务器安装宝塔Linux面板命令脚本大全: 云服务器安装宝塔Linux面板命令 …...
zed2i相机中imu内参的标定及外参标定
zed2i中imu内参的标定 参考: https://blog.csdn.net/weixin_42681311/article/details/126109617 https://blog.csdn.net/weixin_43135184/article/details/123444090 值得注意,imu内参的标定其实不是那么重要,大致上给一个值应该影响不大…...
Java中的JUnit是什么?如何使用JUnit进行单元测试
JUnit是Java中最流行的单元测试框架之一。它可以帮助开发人员在代码编写过程中检测出错误和异常,从而提高代码的质量和可靠性。 什么是JUnit? JUnit是一个由Kent Beck和Erich Gamma创建的开源Java单元测试框架,它已经成为Java开发中最常用的…...
【seata的部署和集成】
seata的部署和集成 seata的部署和集成一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务 二、微服务集成seata1.引入依赖2.修改配置文件 三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取…...
uniapp学习日记之request自定义请求头
uniapp学习日记之request自定义请求头 在学习uniapp的过程中,由于笔者是从Vue项目转来学习uniapp,在使用uni.request时,发现在浏览器调试时,无法在请求头header中添加token字段,愤而弃之,便开始使用axios组…...
【Rust】速度入门---打印个螃蟹先
参考: 菜鸟教程 1 输出到命令行 这不得打印个螃蟹 // 代码来自官方入门教程 // ferris_say需要另外安装 use ferris_says::say; use std::io::{stdout, BufWriter};fn main() {let stdout: std::io::Stdout stdout();let msg: String String::from("Hello fellow Rusta…...
《Linux 内核设计与实现》12. 内存管理
文章目录 页区获得页获得填充为 0 的页释放页 kmalloc()gfp_mask 标志kfree()vmalloc() slab 层slab 层的设计slab 分配器的接口 在栈上的静态分配单页内核栈 高端内存的映射永久映射临时映射 每个 CPU 的分配新的每个 CPU 接口 页 struct page 结构表示系统中的物理页&#x…...
公司新来个卷王,让人崩溃...
最近内卷严重,各种跳槽裁员,相信很多小伙伴也在准备今年的面试计划。 在此展示一套学习笔记 / 面试手册,年后跳槽的朋友可以好好刷一刷,还是挺有必要的,它几乎涵盖了所有的软件测试技术栈,非常珍贵&#x…...
Docker 安全及日志管理
Docker 安全及日志管理 Docker 容器与虚拟机的区别隔离与共享性能与损耗 Docker 存在的安全问题Docker 自身漏洞Docker 源码问题Docker 架构缺陷与安全机制Docker 安全基线标准 容器相关的常用安全配置方法容器最小化Docker 远程 API 访问控制重启 Docker在宿主机的 firewalld …...
大厂面试必备 - MAC 地址 和 IP 地址分别有什么作用?
数据链路层 1、MAC 地址 和 IP 地址分别有什么作用? MAC 地址是数据链路层和物理层使用的地址,是写在网卡上的物理地址。MAC 地址用来定义网络设备的位置。IP 地址是网络层和以上各层使用的地址,是一种逻辑地址。IP 地址用来区别网络上的计…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
UE5 音效系统
一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类,将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix,将上述三个类翻入其中,通过它管理每个音乐…...
