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

【设计模式】1、设计模式七大原则

目录

  • 一、单一职责
  • 二、接口隔离
  • 三、依赖倒置(倒转)
  • 四、里氏替换
  • 五、迪米特法则(Law of Demeter)
  • 六、开闭
  • 七、合成复用

一、单一职责

  • 类(或方法)功能的专一性。一个类(或方法)不应该承担太多功能,一个类(或方法)最好只承担 一种类型 的功能。
public class SingleResponsibility {public static void main(String[] args) {Vehicle vehicle = new Vehicle();vehicle.run("汽车");vehicle.run("火车");vehicle.run("自行车");vehicle.run("飞机"); // 有问题vehicle.run("轮船"); // 有问题}
}class Vehicle {public void run(String vehicleName) {System.out.println(vehicleName + "在公路上行驶");}
}

Vehicle 类既处理陆地上的交通工具,又处理天空中的交通工具;它的作用太广泛了,不单一。


public class SingleResponsibility {public static void main(String[] args) {RoadVehicle roadVehicle = new RoadVehicle();roadVehicle.run("汽车");roadVehicle.run("火车");roadVehicle.run("自行车");SkyVehicle skyVehicle = new SkyVehicle();skyVehicle.run("飞机");WaterVehicle waterVehicle = new WaterVehicle();waterVehicle.run("轮船");}
}class RoadVehicle {public void run(String vehicleName) {System.out.println(vehicleName + "在公路上行驶");}
}class WaterVehicle {public void run(String vehicleName) {System.out.println(vehicleName + "在水中行驶");}
}class SkyVehicle {public void run(String vehicleName) {System.out.println(vehicleName + "在天空中行驶");}
}

在类级别遵循了单一职责原则

当业务功能比较简单的时候也没有必要将其拆分为多个类(如下所示)


public class SingleResponsibility {public static void main(String[] args) {Vehicle vehicle = new Vehicle();vehicle.run("汽车", VehicleType.ROAD);vehicle.run("火车", VehicleType.ROAD);vehicle.run("自行车", VehicleType.ROAD);vehicle.run("飞机", VehicleType.SKY);vehicle.run("轮船", VehicleType.WATER);}
}enum VehicleType {ROAD, WATER, SKY;
}class Vehicle {public void run(String name, VehicleType type) {String sentence = "";if (type == VehicleType.ROAD) {sentence = "在公路上行驶";} else if (type == VehicleType.WATER) {sentence = "在水中行驶";} else if (type == VehicleType.SKY) {sentence = "在天空中行驶";}System.out.println(name + sentence);}// public void roadRun(String name) {}// public void skyRun(String name) {}// public void waterRun(String name) {}
}

Vehicle 类不符合单一职责原则,但其功能简单 。
当功能非常非常简单的时候,不一定必须遵循单一职责原则。(杀鸡别用宰牛刀)

  • 降低了类的功能的复杂度
  • 提高了代码的维护性
  • 代码修改导致连带错误几率降低

二、接口隔离

Clients should not be forced to depend on methods they do not use. 客户端不应该被迫依赖它不使用的方法。
The dependency of one class to another one should depend on the smallest possible interface. 一个类对另一个类的依赖应该建立在最小的接口上。

在这里插入图片描述

public class InterfaceSegregation {public static void main(String[] args) {InOutAbleImpl1 impl1 = new InOutAbleImpl1();InOutAbleImpl2 impl2 = new InOutAbleImpl2();Cat cat = new Cat();cat.use1(impl1);cat.use2(impl1);cat.use3(impl1);Dog dog = new Dog();dog.use1(impl2);dog.use2(impl2);dog.use3(impl2);}
}class Cat {public void use1(InOutAble inOutAble) {inOutAble.openDoor();}public void use2(InOutAble inOutAble) {inOutAble.pushGoods();}public void use3(InOutAble inOutAble) {inOutAble.writeGoodsName();}
}class Dog {public void use1(InOutAble inOutAble) {inOutAble.openDoor();}public void use2(InOutAble inOutAble) {inOutAble.popGoods();}public void use3(InOutAble inOutAble) {inOutAble.writePeopleName();}
}/*** 存取东西的接口*/
interface InOutAble {// 类型1void openDoor(); // 打开门// 类型2void pushGoods(); // 放入货物void writeGoodsName(); // 登记货物名字// 类型3void popGoods(); // 取出货物void writePeopleName(); // 登记取货人的名字
}class InOutAbleImpl1 implements InOutAble {@Overridepublic void openDoor() {System.out.println("InOutAbleImpl1 - openDoor");}@Overridepublic void pushGoods() {System.out.println("InOutAbleImpl1 - pushGoods");}@Overridepublic void writeGoodsName() {System.out.println("InOutAbleImpl1 - writeGoodsName");}@Overridepublic void popGoods() {System.out.println("InOutAbleImpl1 - popGoods");}@Overridepublic void writePeopleName() {System.out.println("InOutAbleImpl1 - writePeopleName");}
}class InOutAbleImpl2 implements InOutAble {@Overridepublic void openDoor() {System.out.println("InOutAbleImpl2 - openDoor");}@Overridepublic void pushGoods() {System.out.println("InOutAbleImpl2 - pushGoods");}@Overridepublic void writeGoodsName() {System.out.println("InOutAbleImpl2 - writeGoodsName");}@Overridepublic void popGoods() {System.out.println("InOutAbleImpl2 - popGoods");}@Overridepublic void writePeopleName() {System.out.println("InOutAbleImpl2 - writePeopleName");}
}

在这里插入图片描述


在这里插入图片描述

public class InterfaceSegregation {public static void main(String[] args) {OpenPushImpl impl1 = new OpenPushImpl();OpenPopImpl impl2 = new OpenPopImpl();Cat cat = new Cat();cat.use1(impl1);cat.use2(impl1);cat.use3(impl1);Dog dog = new Dog();dog.use1(impl2);dog.use2(impl2);dog.use3(impl2);}
}class Cat {public void use1(OpenPushImpl openPushImpl) {openPushImpl.openDoor();}public void use2(OpenPushImpl openPushImpl) {openPushImpl.pushGoods();}public void use3(OpenPushImpl openPushImpl) {openPushImpl.writeGoodsName();}
}class Dog {public void use1(OpenPopImpl openPopImpl) {openPopImpl.openDoor();}public void use2(OpenPopImpl openPopImpl) {openPopImpl.popGoods();}public void use3(OpenPopImpl openPopImpl) {openPopImpl.writePeopleName();}
}interface OpenDoorAble {void openDoor(); // 打开门
}interface PushAble {void pushGoods(); // 放入货物void writeGoodsName(); // 登记货物名字
}interface PopAble {void popGoods(); // 取出货物void writePeopleName(); // 登记取货人的名字
}class OpenPushImpl implements OpenDoorAble, PushAble {@Overridepublic void openDoor() {System.out.println("OpenPushImpl - openDoor");}@Overridepublic void pushGoods() {System.out.println("OpenPushImpl - pushGoods");}@Overridepublic void writeGoodsName() {System.out.println("OpenPushImpl - writeGoodsName");}
}class OpenPopImpl implements OpenDoorAble, PopAble {@Overridepublic void openDoor() {System.out.println("OpenPopImpl - openDoor");}@Overridepublic void popGoods() {System.out.println("OpenPopImpl - popGoods");}@Overridepublic void writePeopleName() {System.out.println("OpenPopImpl - writePeopleName");}
}

三、依赖倒置(倒转)

🍬 ① 高层模块不应该依赖低层模块(类),二者都应该依赖于抽象(接口)
🍬 ② 抽象(接口)不应该依赖细节(实现类),而是细节依赖于抽象
🍬 ③ 依赖倒置的中心思想是:面向接口(抽象)编程
🍬 ④ 依赖倒置设计理念:相对于细节的多变性,抽象的东西要稳定得多。以抽象为基础搭建的架构比以细节为基础搭建的架构要稳定
🍬 ⑤ 使用接口或抽象类的作用是:制定规范(协议);把展现细节的任务交给接口的实现类

接口 ➡️ 抽象
实现类 ➡️ 细节

public class DependencyInversion {public static void main(String[] args) {Person person = new Person();person.sendMessage(new QQMessage("用QQ问候一下小明"));person.sendMessage(new WechatMessage("用微信问候一下小明"));}
}class Person {public void sendMessage(QQMessage qqMessage) {System.out.println(qqMessage.buildMessage());}public void sendMessage(WechatMessage wechatMessage) {System.out.println(wechatMessage.buildMessage());} 
}class QQMessage {private String message;public QQMessage(String message) {this.message = message;}public String buildMessage() {return "QQ Message: " + message;}
}class WechatMessage {private String message;public WechatMessage(String message) {this.message = message;}public String buildMessage() {return "Wechat Message: " + message;}
} 

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

😰 假如版本升级,还想发送 抖音消息 的话:① 需要创建一个 TiktokMessage 类;② 需要在 Person 类中再重载一个 sendMessage(TiktokMessage tiktokMessage) 方法
😰 每次版本升级,增加新的发送消息的方式的时候对代码的改动非常大。假如不止一个用户(不仅仅只有 Person 类),哪改动就更加巨大了


面向接口编程:

在这里插入图片描述

public class DependencyInversion {public static void main(String[] args) {Person person = new Person();person.sendMessage(new QQMessage("用QQ问候一下小明"));person.sendMessage(new WechatMessage("用微信问候一下小明"));}
}class Person {public void sendMessage(IMessage iMessage) {System.out.println(iMessage.buildMessage());}
}interface IMessage {String buildMessage();
}/*** 发送 QQ 消息*/
class QQMessage implements IMessage {private String message;public QQMessage(String message) {this.message = message;}@Overridepublic String buildMessage() {return "QQ Message: " + message;}
}/*** 发送微信消息*/
class WechatMessage implements IMessage {private String message;public WechatMessage(String message) {this.message = message;}public String buildMessage() {return "Wechat Message: " + message;}
}

四、里氏替换

继承优点: 🍬 提高代码的复用性(子类继承父类后可使用父类的非 private 关键字修饰的的成员)

public class Animal {public void eat() {System.out.println("Animal - public void eat()");}protected void drink() {System.out.println("Animal - protected void drink()");}void play() {System.out.println("Animal - void play()");}
}class Dragon extends Animal {public void use() {eat(); // Animal - public void eat()drink(); // Animal - protected void drink()play(); // Animal - void play()}public static void main(String[] args) {Dragon dragon = new Dragon();dragon.use();}
}

继承缺点: 🍬 ① 继承关系过去庞大的话,整个代码结构会很乱
🍬 ② 代码耦合性变高
🍬 ③ 代码稳定性变差(子类可以重写父类的方法。重写之后,运行时究竟调用的是父类的方法还是子类重写的方法很难判断)
🍬 ④ 如果有多处直接使用父类方法的实现,但凡父类方法修改了,所有依赖该父类方法的地方都得考虑兼容性(考虑代码是否会产生 bug)


(1) 子类可以实现父类的抽象方法,【不要覆盖父类的非抽象方法】 (2) 子类可以可以增加自己特有的实现,不要影响父类的非抽象方法【你用父类的可以,但不要改】 (3) 子类方法重载父类方法的时候,方法的形参要比父类方法的形参更宽松(父类方法的形参得是子类方法的形参的父类型)
public class Main {public static void main(String[] args) {Parent parent = new Parent();parent.m2(new ArrayList<>());Son son = new Son();son.m2(new ArrayList<>());/*Parent - m2(ArrayList<String>)Parent - m2(ArrayList<String>)*/}
}class Parent {public void m1() {System.out.println("Parent - m1()");}public void m2(ArrayList<String> list) {System.out.println("Parent - m2(ArrayList<String>)");}
}class Son extends Parent {// 不符合里氏替换原则(子类不应该重写父类的非抽象方法)@Overridepublic void m1() {System.out.println("Son - m1()");}// 子类重载父类的方法(子类重载的方法的参数类型要比父类被重载的方法的参数类型大)// 这样才符合里氏替换原则, 子类增加代码(如新增一个方法)不会影响父类方法的使用public void m2(List<String> list) {System.out.println("Son - m2(List<String>)");}
}
(4) 子类实现父类的抽象方法的时候,方法的返回值应比父类的更加严格

五、迪米特法则(Law of Demeter)

🍬 只与你的直接朋友交谈,不与陌生人交谈【降低类与类之间的耦合】

A ➡️ B ➡️ C
① A 和 B 是直接朋友
② B 和 C 是直接朋友
③ A 和 C 是陌生人
④ 若 A 想使用 C 中的方法,需要通过 B

🍬 直接朋友:
① 当前对象本身
② 当前对象的成员变量
③ 当前对象的成员方法的返回类型
④ 当前对象的成员方法的参数

class Parent {public void m() {// 在方法内部 new 出来的是非直接朋友User user = new User();}
} class User {}

六、开闭

🎄 Open Close Principe:软件对象(类、模块、方法等)应该对扩展开放,对修改关闭
🎄 用抽象构建框架,用实现扩展细节
🎄 开放 服务方 的拓展,关闭 消费方 的修改


public class OpenClosePrincipe {public static void main(String[] args) {// 对消费方的修改关闭// 尽量少修改原先的代码MilkTeaFactory factory = new MilkTeaFactory();factory.makeMilkTea(MilkTeaType.APPLE);factory.makeMilkTea(MilkTeaType.BANANA);}
}interface MilkTeaAble {}class AppleMilkTea implements MilkTeaAble {public AppleMilkTea() {System.out.println("苹果奶茶");}
}class BananaMilkTea implements MilkTeaAble {public BananaMilkTea() {System.out.println("香蕉奶茶");}
}enum MilkTeaType {APPLE, BANANA
}class MilkTeaFactory {public MilkTeaAble makeMilkTea(MilkTeaType type) {switch (type) {case APPLE:return new AppleMilkTea();case BANANA:return new BananaMilkTea();}return null;}
}

public class OpenClosePrincipe {// 修改依赖的类型(消费方代码没有修改)private static MilkTeaAble factory = new WatermelonMilkTeaFactory();public static void main(String[] args) {factory.milkTea();}
}interface MilkTeaAble {void milkTea();
}class AppleMilkTeaFactory implements MilkTeaAble {@Overridepublic void milkTea() {System.out.println("苹果奶茶");}
}class BananaMilkTeaFactory implements MilkTeaAble {@Overridepublic void milkTea() {System.out.println("香蕉奶茶");}
}class WatermelonMilkTeaFactory implements MilkTeaAble {@Overridepublic void milkTea() {System.out.println("西瓜奶茶");}
}

七、合成复用

📖 通过对象 组合、聚合、依赖 达成代码复用,而不是继承

class Animal {public void eat() {System.out.println("Animal - eat()");}public void drink() {System.out.println("Animal - drink()");}public void play() {System.out.println("Animal - play()");}
}/*** 继承(不推荐, 不符合合成复用原则)*/
class People1 extends Animal {public void use() {eat();drink();play();}
}/*** 依赖(推荐)*/
class People2 {public void use(Animal animal) {animal.eat();animal.drink();animal.play();}
}/*** 聚合(推荐)*/
class People3 {private Animal animal;public void setAnimal(Animal animal) {this.animal = animal;}public void use() {animal.eat();animal.drink();animal.play();}
}/*** 组合(推荐)*/
class People4 {private Animal animal = new Animal();public void use() {animal.eat();animal.drink();animal.play();}
}

相关文章:

【设计模式】1、设计模式七大原则

目录一、单一职责二、接口隔离三、依赖倒置&#xff08;倒转&#xff09;四、里氏替换五、迪米特法则&#xff08;Law of Demeter&#xff09;六、开闭七、合成复用一、单一职责 类&#xff08;或方法&#xff09;功能的专一性。一个类&#xff08;或方法&#xff09;不应该承担…...

【前端老赵的CSS简明教程】10-1 CSS预处理器和使用方法

大家好,欢迎来到本期前端课程。我是前端老赵,今天的课程将讲解CSS预处理器的概念和使用方法,希望能够帮助大家更好地进行前端开发。 CSS预处理器是什么? CSS预处理器是一种将类似CSS的语言转换为CSS的工具。它们提供了许多额外的功能,如变量、嵌套、混入、函数等等。这些…...

BFC详解

1. 引言 在前端的布局手段中&#xff0c;一直有这么一个知识点&#xff0c;很多前端开发者都知道有它的存在&#xff0c;但是很多人也仅仅是知道它的存在而已&#xff0c;对它的作用也只是将将说得出来&#xff0c;可是却没办法说得非常的清晰。这个知识点&#xff0c;就是BFC…...

C++:哈希结构(内含unordered_set和unordered_map实现)

unordered系列关联式容器 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到$log_2 N$&#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;当树中的节点非常多时&#xff0c;查询效率也不理想。最好 的查询是&#xff…...

Java实现调用第三方相关接口(附详细思路)

目录1.0.简单版2.0.升级版2-1.call.timeout()怎么传入新的超时值2-2.timeout(10, TimeUnit.SECONDS)两个参数的意思&#xff0c;具体含义3.0.进阶版3-1.java.net.SocketTimeoutException: 超时如何解决4.0.终极版1.0.简单版 以下是一个使用 Java 实际请求“第三方”的简单示例代…...

基础数据结构:单链表

今天懒洋洋学习了关于基础数据结构有关单链表的相关操作&#xff0c;懒洋洋来这温习一下。一:单链表的定义链表定义&#xff1a;用链式存储的线性表统称为链表&#xff0c;即逻辑结构上连续&#xff0c;物理结构上不连续。链表分类&#xff1a;单链表、双链表、循环链表、静态链…...

基于51单片机的智能计算器Protues仿真设计

目录 一、设计背景 二、实现功能 三、硬件设计 3.1 总体硬件设计 ​3.2 键盘电路的设计 3.3 显示电路的设计 四、仿真演示 五、源程序 一、设计背景 随着社会的发展&#xff0c;科学的进步&#xff0c;人们的生活水平在逐步的提高&#xff0c;尤其是微电子技术的发展&am…...

Pandas数据分析实战练习

Pandas数据分析实战练习 文章目录 Pandas数据分析实战练习一、读取Excel文件中的数据1、读取工号、姓名、时段、交易额这四列数据,使用默认索引,输出前10行数据2、读取第一个worksheet中所有列,跳过第1、3、5行,指定下标为1的列中数据为DataFrame的行索引标签二、筛选符合特…...

C++ 继承下(二篇文章学习继承所有知识点)

5.继承与友元友元关系不能继承&#xff0c;也就是说基类友元不能访问子类私有和保护成员 //验证友元不能继承 class B {friend void Print(); public:B(int b): _b(b){cout << "B()" << endl;}protected:int _b; };class D : public B { public:D(int b,…...

【C++】C++11新特性——类的改进|lambda表达式

文章目录一、类的改进1.1 默认生成1.2 移动构造函数1.3 移动赋值重载函数1.4 成员变量缺省值1.5 强制生成默认函数的关键字default1.6 禁止生成默认函数的关键字delete1.6.1 C98防拷贝1.6.1 C11防拷贝二、lambda表达式2.1 对比2.2 lambda表达式语法2.3 捕捉列表2.4 函数对象与l…...

C语言进阶(37) | 程序环境和预处理

目录 1.程序的翻译环境和执行环境 2.详解编译链接 2.1 翻译环境 2.2 编译本身也分为几个阶段: 2.3 运行环境 3.预处理详解 3.1预定符号 3.2 #define 3.3 #undef 3.4 命令行定义 3.5 条件编译 3.6 文件包含 了解重点&#xff1a; 程序的翻译环境程序的执行环境详解: C语言程…...

Golang每日一练(leetDay0005)

目录 13. 罗马数字转整数 Roman to Integer ★ 14. 最长公共前缀 Longest Common Prefix ★ 15. 三数之和 3Sum ★★★ &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 13. 罗马数字转…...

occt_modeling_data(一)——拓扑

下面是我基于opencascade英文文档中关于occt_modeling_data中Topology部分进行的翻译&#xff0c;英文好的还是建议直接看文档&#xff0c;部分我不肯定的地方我会附上英文原句。如发现有错误欢迎评论区留言。 OCCT Topolog允许用户访问和操纵物体的数据&#xff0c;且不需要处…...

【AcWing】蓝桥杯备赛-深度优先搜索-dfs(3)

目录 写在前面&#xff1a; 题目&#xff1a;93. 递归实现组合型枚举 - AcWing题库 读题&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 数据范围&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 解题思路&#xff1a; 代码&#xff1a; AC &…...

宇宙最强-GPT-4 横空出世:最先进、更安全、更有用

文章目录前言一、准确性提升1.创造力2.视觉输入3.更长的上下文二、相比于ChatGPT有哪些提升1.GPT-4 的高级推理能力超越了 ChatGPT2.GPT-4 在多种测试考试中均优于 ChatGPT。三、研究团队在GPT-4模型都做了哪些改善1.遵循 GPT、GPT-2 和 GPT-3 的研究路径2.我们花了 6 个月的时…...

HashMap的实际开发使用

目 录 前言 一、HashMap是什么&#xff1f; 二、使用步骤 1.解析一下它实现的原理 ​编辑 2.实际开发使用 总结 前言 本章&#xff0c;只是大概记录一下hashMap的简单使用方法&#xff0c;以及理清一下hashMap的put方法的原理&#xff0c;以及get方法的原理。 一、Has…...

OpenCV入门(十三)快速学会OpenCV 12 图像梯度

OpenCV入门&#xff08;十三&#xff09;快速学会OpenCV 12 图像梯度1.Sobel算子1.1 计算x1.2 计算y1.3 计算xy2.Scharr算子2.1 计算x2.2 计算y2.3 计算xy3.Laplacian算子4.总结图像梯度计算的是图像变化的速度。对于图像的边缘部分&#xff0c;其灰度值变化较大&#xff0c;梯…...

软考:常见小题目计算题

01采购合同的类型采购合同主要包括总价类合同、成本补偿类合同、工料合同三大类合同。1、总价类合同此类合同为既定产品、服务或成果的采购设定一个总价。这种合同应在已明确定义需求&#xff0c;且不会出现重大范围变更的情况下使用。包括&#xff1a;&#xff08;1&#xff0…...

【Linux】进程的程序替换

文章目录1. 程序替换1.创建子进程的目的是什么&#xff1f;2.了解程序是如何进行替换的3. 程序替换的基本原理当创建进程的时候&#xff0c;先有进程数据结构&#xff0c;还是先加载代码和数据&#xff1f;程序替换是整体替换&#xff0c;不是局部替换execl 返回值4. 替换函数1…...

【C++】模板(上)

文章目录1、泛型编程2、函数模板函数模板的实例化模板参数的匹配原则3、 类模板类模板的实例化1、泛型编程 void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& left, double& right) {double temp left;left …...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...