设计模式之六大设计原则
文章目录
- 高内聚低耦合
- 设计原则
- 开闭原则
- 单一职责原则
- 里氏代换原则
- 依赖倒置原则
- 迪米特原则
- 接口隔离原则
高内聚低耦合
提高代码的可读性、可维护性和可扩展性,降低开发和维护的成本,并减少系统的风险
内聚:
内聚表示一个模块内部各个元素之间相互关联的程度。
高内聚意味着模块内部的功能紧密相关,所有部分都共同完成一个特定的任务或功能。
低内聚则意味着模块内部包含多种不相关的功能。
耦合:
耦合表示不同模块之间相互依赖的程度。
高耦合意味着模块之间相互依赖紧密,一个模块的变化会影响到其他模块。
低耦合则意味着模块之间相对独立,一个模块的变化对其他模块的影响较小。
举个例子:
汽车是由许多不同的部件组成的,比如发动机、轮胎、刹车等等。
在高内聚低耦合的设计中,每个部件都应该专注于自己的功能,同时尽可能减少与其他部件之间的依赖关系。
高内聚意味着每个部件都应该有一个清晰的责任和功能。发动机的责任是提供动力,而刹车系统的责任是提供制动。这样设计的好处是,每个部件都可以独立工作,而不需要过多依赖其他部件的内部细节。
低耦合意味着部件之间的相互依赖应该尽可能减少。刹车系统不需要知道发动机如何工作,它只需要知道何时需要制动。这样设计的好处是,如果需要更改或替换一个部件,不会对其他部件产生太大影响,因为它们之间的依赖关系很少。
高内聚:意味着一个类或模块的内部元素(包括变量、方法和属性)应该紧密相关,并且共同服务于一个明确且集中的目的。
低耦合:模块或类之间的依赖关系应该尽可能少
- 内紧(高内聚):程序内的模块或类应该紧密相关,形成一个高效的功能单元。
- 外松(低耦合):程序之间的模块或类应该尽可能不关联,各自实现各自的功能。
设计原则
在进行软件系统设计时所要遵循的一些经验准则,应用该准则的目的通常是为了避免某些经常出现的设计缺陷,提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性
包括单一职责原则,开放封闭原则,里氏替换原则,依赖倒置原则,迪米特原则,接口隔离原则
开闭原则
(Open-Closed Principle, OCP)
定义:类,模块,函数等应该是可以拓展的,但是不可修改
对扩展开放,对修改关闭。
我们需要使用抽象实现(接口和抽象类)达到这样的效果。
因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。
而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
举个例子
//AbstractSkin.java
public abstract class AbstractSkin {//显示皮肤public abstract void display();
}//DefaultSkin.java
public class DefaultSkin extends AbstractSkin{@Overridepublic void display() {System.out.println("默认皮肤");}
}//WhiteSkin.java
public class WhiteSkin extends AbstractSkin{@Overridepublic void display() {System.out.println("白色皮肤");}
}//SougouInput.java
public class SougouInput {private AbstractSkin skin;public AbstractSkin getSkin() {return skin;}//通过setSkin方法设置不同的皮肤实现public void setSkin(AbstractSkin skin) {this.skin = skin;}public void display() {skin.display();}
}//Client.java
public class Client {public static void main(String[] args) {//1.创建输入法对象SougouInput input = new SougouInput();//2.创建皮肤对象DefaultSkin skin = new DefaultSkin();//WhiteSkin skin = new WhiteSkin();//3.将皮肤设置到输入法中input.setSkin(skin);//4.显示皮肤input.display();}
}
SougouInput 类通过其 setSkin 方法允许添加不同类型的皮肤(如 DefaultSkin 或 WhiteSkin),这体现了对扩展的开放性。
由于 SougouInput 类依赖于 AbstractSkin 抽象类而不是具体的皮肤实现类,因此添加新的皮肤类型只需要创建新的子类并实现 AbstractSkin 的 display 方法,而不需要修改 SougouInput 类的代码。这体现了对修改的封闭性。
皮肤的类不用修改,再创建新皮肤,让他继承AbstractSkin抽象类,在客户端类代码进行修改即可。
作用:
- 提高软件的可维护性
- 增强软件的扩展性
- 减少代码的耦合度
单一职责原则
(Single Responsibility Principle,SRP)
定义:一个类(或模块、函数等)应该只有一个引起它变化的原因。换句话说,一个类应该只负责一个功能领域中的相关职责,或者变化的原因应该只有一个。
下面是不符合单一职责原则的例子:
public class TelPhone {public void Dial(String phone_number){System.out.println("给"+phone_number+"打电话");}public void HangUp(String phone_number) {System.out.println("挂断" + phone_number + "打电话");}public void SendMessage(String message) {System.out.println("发送" + message);}public void ReceiveMessage(String message) {System.out.println("接收" + message);}
}
可能发生的变化:
-
内部的变化,如果
TelPhone类中的任何一个方法发生改变,,都需要修改TeIPhone、由于它负责了多个职责,所以一个职责的变化可能会导致其他无关职责的代码也需要被修改或重新测试。 -
外部的变化,如果
TeIPhone要添加新的的方法,需要修改TeIPhone类
为了符合单一职责原则,我们可以做出如下修改:
但中间的依然不符合,存在一个以上引起类变化的原因,所以我们可以考虑最右边的,一个类中只有一个方法

但这样比较极端,会导致类的数量大幅增加,使得管理和维护代码变得复杂。
因此,我们通常要在单一职责原则和实际应用之间找到一个平衡点。
实现方式:
给每个方法,都提炼成一个接口,抽象成一种能力,然后分别写类,去实现接口,最终在TelPhone中只进行调用。
package com.feng.test01;interface Dialer {void Dial(String phoneNumber);
}interface Hanger {void HangUp();
}interface Sender {void SendMessage(String text);
}interface Receiver {void ReciveMessage(String text);
}class DialerImpl implements Dialer {public void Dial(String phoneNumber) {System.out.println("给 " + phoneNumber + " 打电话");}
}class HangerImpl implements Hanger {public void HangUp() {System.out.println("挂断电话");}
}class SenderImpl implements Sender {public void SendMessage(String text) {System.out.println("发送 " + text);}
}class ReceiverImpl implements Receiver {public void ReciveMessage(String text) {System.out.println("接收 " + text);}
}class TelPhone {private Dialer dialer;private Hanger hanger;private Sender sender;private Receiver receiver;public TelPhone(Dialer dialer, Hanger hanger, Sender sender, Receiver receiver) {this.dialer = dialer;this.hanger = hanger;this.sender = sender;this.receiver = receiver;}public void Dial(String phoneNumber) {dialer.Dial(phoneNumber);}public void HangUp() {hanger.HangUp();}public void SendMessage(String text) {sender.SendMessage(text);}public void ReciveMessage(String text) {receiver.ReciveMessage(text);}
}public class Main {public static void main(String[] args) {// 创建接口实现类实例Dialer dialer = new DialerImpl();Hanger hanger = new HangerImpl();Sender sender = new SenderImpl();Receiver receiver = new ReceiverImpl();// 创建 TelPhone 对象并使用其接口TelPhone telphone = new TelPhone(dialer, hanger, sender, receiver);// 电话呼叫操作telphone.Dial("123456789");telphone.HangUp();// 消息操作telphone.SendMessage("Hello, World!");telphone.ReciveMessage("Hi there!");}
}
好处:
- 提高代码的可读性,提高系统的可维护性。
- 降低类的复杂性,一个模块只负责一个职责,提高系统的可扩展性和可维护性。
- 降低变更引起的风险。变更是不然的,如果单一职责做得好,当修改一个功能的时候可以显著的降低对另一个功能的影响。
里氏代换原则
(Liskov Substitution Principle,LSP)
里氏代换原则:任何基类可以出现的地方,子类一定可以出现。
通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。
要点:
功能保持:子类应当能够替代基类,并且子类对象应能代替基类对象使用,而不会导致程序运行出现问题。
行为一致:子类可以扩展基类的功能,但不能改变基类的功能。即子类的行为应该与基类保持一致
要求:
- 子类可以实现父类的抽象方法,但不要去覆盖(重写)父类的非抽象方法
- 子类可以增加自己特有的方法
- 当子类的方法重写父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松
- 当子类的方法实现父类的方法时(重写或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或与父类一样
package com.feng.test05;public abstract class Coder {public void coding() {System.out.println("我会敲代码!");}
}class JavaCoder extends Coder {public void play() {System.out.println("喜欢玩XXXX");}//重写了父类的非抽象方法public void coding() {System.out.println("我只会敲JAVA代码!");}
}
里氏代换原则指出,如果程序中的对象使用的是基类(父类)的话,那么无论是使用基类对象还是其子类对象,程序的行为都是一致的。
用 JavaCoder 替代 Coder 时,本来会敲很多代码,但现在只会敲JAVA了。
所以尽量不要去重写父类非抽象方法,不要改变父类原有的功能。
可以这样修改:
- 保留父类方法的行为,并且扩展子类方法的功能
public void coding() {super.coding(); // 调用父类的coding方法System.out.println("我会敲JAVA代码!");}
- 或者再写一个
javaCoding方法 - 写
JavaCoder和Coder的抽象父类People,把coding这一行为定义在People中,放弃JavaCoder和Coder的继承关系
好处:
- 开放性:是实现开放封闭原则的的具体手段之一
- 提高代码的可复用性
依赖倒置原则
(Dependence Inversion Principle,DIP)
定义:高层模块不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。
旨在通过依赖于抽象而不是具体实现来降低系统的耦合度,提高系统的可维护性和可扩展性。
下面是一个违背依赖倒置原则的例子
package com.feng.test04;class FuelCar{public void run(){System.out.println("开的是燃油车");}
}class Driver{public void drive(FuelCar car) {car.run();}
}public class Client {public static void main(String[] args) {FuelCar fuelCar = new FuelCar();Driver xiaowang = new Driver();xiaowang.drive(fuelCar);}
}
Driver 类直接依赖于 FuelCar 类,而没有使用抽象,违反了依赖倒置原则。
如果我们想要支持其他类型的车辆,比如电动车或者公交车,就需要修改 Driver 类,这样会增加代码的耦合度和维护成本。
高层模块(Driver)不应该直接依赖于低层模块(FuelCar),而是应该依赖于抽象。在这个例子中,Driver 类应该依赖于一个抽象的 ICar 接口,而不是具体的 FuelCar 类。
我们可以引入一个接口来表示所有类型的车,并让FuelCar实现这个接口。然后,Driver的drive方法可以接受任何实现了ICar接口的对象作为参数。
package com.feng.test04after;interface ICar {void run();
}class FuelICar implements ICar {@Overridepublic void run() {System.out.println("开的是燃油车");}
}class ElectricICar implements ICar {@Overridepublic void run() {System.out.println("开的是电车");}
}class Driver {public void drive(ICar car) {car.run();}
}public class Client {public static void main(String[] args) {ICar su7 = new ElectricICar();ICar benz = new FuelICar();Driver driver = new Driver();driver.drive(su7);driver.drive(benz);}
}
作用:
- 提高代码的可维护性
- 降低代码的耦合度
- 提高系统的可扩展性
迪米特原则
(Law of Demeter,LoD)
也称为最少知识原则:一个对象应该对其他对象有最少的了解。
定义:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用
一个对象应该对其他对象知之甚少,只与“朋友”通信,而不与“陌生人”直接通信。
- 租房者-中介-房东
- 要做软件的公司-软件公司-软件工程师
这里的“朋友”指的是当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等
这些对象同当前对象存在关联、依赖、聚合或组合关系,可以直接访问这些对象的方法。
下面是一个
import java.util.ArrayList;
import java.util.List;class Product {private String name;private double price;public Product(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public double getPrice() {return price;}
}// 购物车类
class ShoppingCart {private List<Product> products;public ShoppingCart() {this.products = new ArrayList<>();}// 添加商品到购物车public void addProduct(Product product) {products.add(product);}// 打印购物车中的商品信息public void printCart() {for (Product product : products) {System.out.println("商品:" + product.getName() + " 价格:" + product.getPrice());}}
}public class Test {public static void main(String[] args) {Product product1 = new Product("banana", 2);Product product2 = new Product("apple", 5);ShoppingCart cart = new ShoppingCart();cart.addProduct(product1);cart.addProduct(product2);cart.printCart();}
}
ShoppingCart 类对 Product 类的了解仅限于 getName 和 getPrice 方法,这是符合迪米特原则的。ShoppingCart 不需要知道 Product 类的内部实现细节,也不需要与其他任何与 Product 类相关的“陌生人”对象进行交互。
好处:
- 降低耦合性
- 提高模块独立性
- 增强系统的可维护性
接口隔离原则
(Interface Segregation Principle,ISP)
定义:一个类对另一个类的依赖应该建立在最小的接口上。
建立单一接口,不要建立庞大臃肿的接口;尽量细化接口,接口中的方法尽量少。
也就是说,我们要为各个类建立专用的接口,而不要试图建立一个很庞大的接口件所有依赖它的类通用。
下面是一个不符合接口隔离原则的例子:
package com.feng.test03;interface Device {String getCpu();String getType();String getMemory();
}
class computer implements Device{@Overridepublic String getCpu() {return "i7";}@Overridepublic String getType() {return "笔记本电脑";}@Overridepublic String getMemory() {return "16GB";}
}class fan implements Device{@Overridepublic String getCpu() {return null; //不需要的方法}@Overridepublic String getType() {return "电风扇";}@Overridepublic String getMemory() {return null; //不需要的方法}
}
虽然定义了一个Device接口,但是由于此接口的粒度不够细化,类依赖于不需要的方法。虽然比较契合电脑这种设备,但是不适合风扇,要对其进行更细粒度的划分。
接口的粒度:描述了接口所提供功能的大小和复杂度
下面是一个符合接口隔离原则粒度更细的代码:
// 通用设备接口
interface GenericDevice { String getType();
} // 电脑设备接口
interface ComputerDevice extends GenericDevice { String getCpu(); String getMemory();
} // 风扇设备接口
interface FanDevice extends GenericDevice {void adjustSpeed(int speed);
}
注意:
- 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计的灵活性;但是如果过小,则会造成接口数量过多,使设计复杂化。所以,接口的大小一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类需要的方法,不需要的方法则隐藏起来只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互。接口方法尽量少用
public修饰。接口是对外的承诺,承诺越少,对系统的开发越有利,变更风险也会越少。
作用:
- 降低耦合性
- 提高灵活性
- 增强可维护性
- 开闭原则:抽象架构,扩展实现
- 单一职责:一个类和方法只做一件事
- 里氏替换: 多态,子类可扩展父类
- 依赖倒置:细节依赖抽象,下层依赖上层
- 接口隔离:建立单一接口
- 迪米特原则:最少知道,降低耦合
参考:
- 14.设计模式-设计原则(依赖倒转原则概述和案例)
- 【设计模式】六大原则详解
- 六大设计原则超详细介绍
- 面向对象设计原则
如有错误烦请指正。
感谢您的阅读
相关文章:
设计模式之六大设计原则
文章目录 高内聚低耦合设计原则开闭原则单一职责原则里氏代换原则依赖倒置原则迪米特原则接口隔离原则 高内聚低耦合 提高代码的可读性、可维护性和可扩展性,降低开发和维护的成本,并减少系统的风险 内聚: 内聚表示一个模块内部各个元素之间…...
【iOS】UI学习(一)
UI学习(一) UILabelUIButtonUIButton事件 UIViewUIView对象的隐藏UIView的层级关系 UIWindowUIViewController定时器与视图对象 UISwitch UILabel UILabel是一种可以显示在屏幕上,显示文字的一种UI。 下面使用代码来演示UILabel的功能&#…...
如何使用Vue和Markdown实现博客功能
创建Vue项目和安装依赖 npm install -g @vue/cli vue create vue-blog cd vue-blog npm install vue-markdown-loader --save-dev配置Vue项目以解析Markdown 在 vue.config.js 文件中添加以下配置: module.exports = {chainWebpack: config => {config...
1初识C#
1、Console安慰 Console.WriteLine("Hello, world!"); // 输出 "Hello, world!" 并换行 Console.WriteLine(123.45); // 输出数字 123.45 并换行 Console.WriteLine("Name: " name); // 输出 "Name: [变量name的值]" 并换行 2、 C…...
查询指定会话免打扰
查询指定用户(requestId) 为指定会话(targetId)的设置的免打扰状态。 提示 该设置为用户级别设置。对应的设置接口详见设置指定会话免打扰。 请求方法 POST: https://数据中心域名/conversation/notification/get.json 频率限…...
Linux-命令
添加权限方法及注意事项: 字母权限法很灵活,无论目录还是文件都可以随意添加删除超级权限 chmod us ... 添加SUID chmod gs ... 添加SGID chmod s ...同时添加SUID和SGID chmod -s ...同时删除SUID和SGID chmod ot ...添加Sticky chmod t ...同上 数字权限表示法添加/删除…...
STM32读写内部FLASH读取芯片id
文章目录 读写内部Flash接线程序编写测试效果补充 读取芯片id代码编写 读写内部Flash 接线 程序编写 首先使用ThisFlash.c来写入flash的基本操作,写入、读取、擦除,然后使用Store.c配合数组来进行主存与flash的交互 ThisFlash.c #include "stm32…...
前端npm打包及报错解决
前端npm install 安装node 下载地址 https://nodejs.org/en/download/prebuilt-binaries 配置环境变量 wget https://nodejs.org/dist/v14.21.3/node-v14.21.3-linux-x64.tar.xz tar xf node-v14.21.3-linux-x64.tar.xz -C /data/ vim /etc/profile export NODE_HOME/data/n…...
vbs执行报错vbs没有文件拓展,双击无法打开
如果看不到文件扩展名需要设置: 无法双击打开vbs 一般为注册表问题 解决办法 将下方代码保存为xxx.reg Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.VBS] "VBSFile" [HKEY_CLASSES_ROOT.VBS\PersistentHandler] "{5e941d80-bf96-…...
超详细的前后端实战项目(Spring系列加上vue3)前端篇(二)(一步步实现+源码)
好了,兄弟们,继昨天的项目之后,开始继续敲前端代码,完成前端部分 昨天完成了全局页面的代码,和登录页面的代码,不过昨天的代码还有一些需要补充的,这里添加一下 内容补充:在调用登…...
【国产中颖】SH79F9202U单片机驱动LCD段码液晶学习笔记
1. 引言 因新公司之前液晶数显表产品单片机一直用的是 C51单片机(SH79F9202U9),本人之前没有接触过这款单片机,为了维护老产品不得不重新研究研究这款单片机。 10位ADC LCD的增强型8051微控制器 SH79F9202是一种高速高效率8051可兼容单片机。在同样振…...
人工智能初识
🌞欢迎来到人工智能基础的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 📆首发时间:🌹2024年5月1…...
【算法刷题day60】Leetcode:84. 柱状图中最大的矩形
文章目录 Leetcode 84. 柱状图中最大的矩形解题思路代码总结 草稿图网站 java的Deque Leetcode 84. 柱状图中最大的矩形 题目:84. 柱状图中最大的矩形 解析:代码随想录解析 解题思路 反方向接雨水。见上一篇文章 代码 class Solution {public int la…...
ThingsBoard物联网网关在智慧城市数据采集中的应用
智慧城市由监控中心、采集网关、前端采集设备、前端感应执行器组成。 为何选用ThingsBoard作为平台 监控中心为物联网平台,该平台包含云计算、大数据、人工智能、物联网、GIS、云安全等主要模块,具备数据采集、数据交换、超大规模计算、数据分析、数据应…...
Java中的打印流PrintStream 和 PrintWriter
PrintStream和PrintWriter在Java中都是用于打印输出的类,但它们之间存在一些明显的区别。以下是关于这两个类的详细解释和比较: PrintStream 基本特性 PrintStream是一个字节打印流,它继承自FilterOutputStream。 主要操作byte流࿰…...
【MATLAB源码-第217期】基于matlab的16QAM系统相位偏移估计HOS算法仿真,对比补偿前后的星座图误码率。
操作环境: MATLAB 2022a 1、算法描述 高阶统计量(HOS)频偏估计算法 高阶统计量(Higher Order Statistics, HOS)频偏估计算法是一种先进的信号处理技术,广泛应用于现代数字通信系统中,以应对…...
C# CryptoStream流的详解与示例
在当今数字时代,数据安全变得越来越重要。保护敏感信息免受未授权访问是每个开发者的责任。在C#中,使用CryptoStream流可以方便地对数据进行加密和解密。本文将详细介绍C# CryptoStream库的用法、功能以及它如何对数据进行加密和解密。 一、CryptoStrea…...
Kubernetes 之 ReplicaSet
Kubernetes 之 ReplicaSet ReplicaSet 定义 ReplicaSet 是 Kubernetes 中的一种副本控制器,其主要作用是控制其管理的 Pod 的预设副本数量。它会持续监听这些 Pod 的运行状态,在Pod发生故障时执行重启策略,当 Pod 数量减少时会重新启动新的…...
转发和重定向
目录 是什么 转发(Forwarding) 概念 特点 实现方式 重定向(Redirecting) 概念 特点 实现方式 转发和重定向区别整理 转发和重定向的适用场景 转发(Forwarding) 重定向(Redirect&am…...
源码部署ELK
目录 资源列表 基础环境 关闭防护墙 关闭内核安全机制 修改主机名 添加hosts映射 一、部署elasticsearch 修改limit限制 部署elasticsearch 修改配置文件 单节点 集群(3台节点集群为例) 启动 二、部署logstash 部署logstash 添加配置文件 启动 三、部署kiban…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
用鸿蒙HarmonyOS5实现中国象棋小游戏的过程
下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...
水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...
