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

系统设计——项目设计经验总结1

摘要

  1. 在系统设计的时候,注意域的区分,功能区分、类的区分、方法区分范围和定义。
  2. 在系统设计的时候的,需要思考类、方法在什么情况下会涉及到修改,遵循记住:一个类应该只有一个原因被修改! 当不满足,可能就考虑拆分的问题。
  3. 学会T泛型使用,因为泛型是通用类型?使用泛型(通用、公共方法,不涉及业务逻辑)、使用具体类型(涉及业务相关使用的具体实现类)。
  4. 使用对象抽象能力。

1. 什么是低耦合,高内聚

低耦合(Low Coupling)和高内聚(High Cohesion)是软件设计中的两个重要原则,它们有助于提高代码的可维护性、可复用性和扩展性。

1.1. 低耦合(Low Coupling)

耦合指的是模块或组件之间的依赖程度。低耦合意味着不同模块之间的依赖性较小,修改一个模块时不会影响或最小影响其他模块。

低耦合的特点:

  • 接口清晰:模块之间通过接口进行交互,而不是直接依赖具体实现。
  • 减少依赖:一个模块的变化不会导致多个模块需要修改。
  • 提高可扩展性:可以独立替换或修改某个模块,而不会影响整体系统。

如何实现低耦合?

  • 使用接口和抽象类,而不是直接依赖具体类。
  • 依赖倒置原则(DIP):依赖于抽象(接口),而不是具体实现。
  • 单一职责原则(SRP):每个模块只负责一个明确的功能,减少不必要的依赖。
  • 避免全局变量和静态方法,降低模块之间的隐藏依赖。

1.2. 高内聚(High Cohesion)

内聚指的是模块内部各个功能之间的关联程度。高内聚意味着一个模块内的功能紧密相关,模块内部的代码共同完成一个明确的任务,而不是负责多个不相关的功能。

高内聚的特点:

  • 单一职责:一个模块专注于完成一项任务,而不是承担多个不同的职责。
  • 增强可读性和可维护性:代码容易理解和修改。
  • 减少代码重复:相似功能集中在同一个模块内,而不是散落在不同模块中。

如何实现高内聚?

  • 遵循单一职责原则(SRP),一个模块只负责一件事。
  • 模块内部方法紧密相关,不包含与主要功能无关的代码。
  • 减少对外暴露的接口,尽量在模块内部解决问题,避免对外部造成不必要的依赖。

1.3. 低耦合 vs. 高内聚示例

二者相辅相成:

  • 高内聚使得模块内部功能紧密相关,保证模块内部的一致性。
  • 低耦合减少模块之间的依赖,使得模块可以独立修改和维护。

1.3.1. 示例反例(高耦合、低内聚)

public class OrderService {public void processOrder() {// 处理订单System.out.println("处理订单");// 发送通知sendEmail();sendSMS();// 记录日志logOrder();}private void sendEmail() {System.out.println("发送邮件通知");}private void sendSMS() {System.out.println("发送短信通知");}private void logOrder() {System.out.println("记录订单日志");}
}
  • 订单处理(核心业务逻辑)和通知(邮件、短信)耦合在一起,修改通知方式需要改 OrderService
  • 订单逻辑、日志记录、通知都混在 OrderService 里,导致内聚度低。

1.3.2. 优化(低耦合、高内聚)

public class OrderService {@Autowiredprivate final NotificationService notificationService;public void processOrder() {System.out.println("处理订单");notificationService.sendNotification();}
}public class NotificationService {public void sendNotification() {System.out.println("发送邮件通知");System.out.println("发送短信通知");}
}
  • 低耦合OrderService 依赖 NotificationService 接口,而不是直接调用通知方法。
  • 高内聚:订单逻辑在 OrderService,通知相关的逻辑在 NotificationService,各自只关注自己的职责。

1.4. 低耦合,高内聚总结

原则

低耦合

高内聚

定义

模块之间的依赖性低

模块内部功能紧密相关

作用

提高系统的灵活性,易于扩展和维护

使模块更易于理解、修改和复用

实现方式

依赖抽象、接口隔离、减少直接依赖

遵循单一职责原则,把相关功能放在一起

典型示例

使用接口、依赖注入(DI)、事件驱动

业务逻辑和工具类分开,方法职责清晰

在实际开发中,低耦合和高内聚是软件设计的重要目标,合理设计可以提高系统的稳定性和可维护性。

2. 什么是单一职责原则(SRP)

定义:一个类(或者模块、方法)应该只有一个引起它变化的原因,即只负责一个职责

这个原则的核心思想是高内聚、低耦合,避免一个类承担过多的职责,从而提高代码的可读性、可维护性和可复用性。

2.1. 如果一个类承担多个职责,就会导致:

  • 代码难以维护:一个职责的修改可能影响另一个不相关的职责。
  • 代码耦合度高:不同职责之间存在隐式依赖,修改一部分可能导致整个类的修改。
  • 测试困难:一个类承担多个职责,测试时可能需要处理不必要的复杂性。

通过遵循 SRP,我们可以:

提高代码可读性:一个类的功能清晰,易于理解。
降低修改成本:只需修改受影响的部分,而不会影响其他功能。
提高复用性:模块职责清晰,可以在不同场景下复用。

2.2. 如何判断一个类是否违反 SRP?

  • 是否有多个原因导致它需要修改?
  • 类中的方法是否处理多个不同的逻辑?
  • 类的功能是否可以拆分成多个独立的部分?
  • 是否可以将不同的功能分配给不同的类?

如果一个类满足以上几个条件,就可能违反了 SRP,需要拆分。

2.3. 代码示例

public class OrderService {public void processOrder() {System.out.println("处理订单");}public void sendEmailNotification() {System.out.println("发送邮件通知");}public void saveOrderToDatabase() {System.out.println("订单数据存入数据库");}
}

问题分析:

  • OrderService 既负责订单处理,又负责通知,还负责数据库操作,承担了多个职责。
  • 如果需要修改通知方式(比如从邮件改成短信),就必须修改 OrderService,影响了订单处理的核心逻辑。

循 SRP 的优化:拆分为三个独立的类,每个类只负责一个职责:

// 订单处理类
public class OrderService {@Autowiredprivate NotificationService notificationService;@Autowiredprivate OrderRepository orderRepository;public void processOrder() {System.out.println("处理订单");orderRepository.saveOrder();notificationService.sendNotification();}
}// 订单数据存储类
public class OrderRepository {public void saveOrder() {System.out.println("订单数据存入数据库");}
}// 通知服务类
public class NotificationService {public void sendNotification() {System.out.println("发送邮件通知");}
}

优化后的好处:

  • 职责分离OrderService 只负责订单处理,OrderRepository 负责数据库存储,NotificationService 负责通知。
  • 修改影响范围小:如果要修改通知方式,只需修改 NotificationService,不会影响 OrderService
  • 可测试性更强:每个类都可以单独测试,避免不相关的代码影响测试。

2.4. 什么时候该拆分?

并不是所有的类都必须拆分,如果拆分过度,会导致代码结构过于复杂,影响可读性。

适合拆分的情况:

  • 职责明显不同:比如订单处理、日志记录、支付等功能应该分开。
  • 不同职责会频繁变更:如果两个功能的变更频率不同,应该拆分。例如,订单逻辑可能经常变化,但日志逻辑可能一直稳定。
  • 职责之间的依赖很弱:如果两个功能可以独立开发、测试和维护,应该拆分。

2.5. SRP 在方法层面的应用

不仅仅是类,方法也应该遵循单一职责原则。

违反 SRP 的方法:

public void processOrder() {// 处理订单System.out.println("处理订单");// 记录日志System.out.println("记录订单日志");// 发送通知System.out.println("发送邮件通知");
}

遵循 SRP 的方法拆分:

public void processOrder() {handleOrder();logOrder();sendNotification();
}private void handleOrder() {System.out.println("处理订单");
}private void logOrder() {System.out.println("记录订单日志");
}private void sendNotification() {System.out.println("发送邮件通知");
}

这样,每个方法只负责一项具体任务,代码更清晰、更易维护。

2.6. SRP 与其他设计原则的关系

  • 与开闭原则(OCP):SRP 使类职责单一,减少对原有代码的修改,提高扩展性。
  • 与依赖倒置原则(DIP):通过拆分职责,可以让高层模块依赖抽象,而不是具体实现。
  • 与接口隔离原则(ISP):如果一个接口承担了多个职责,应该拆分成多个独立的接口。

2.7. 单一职责原则总结

原则

单一职责原则(SRP)

定义

一个类或方法应该只有一个引起它变化的原因,即只负责一个职责。

核心思想

高内聚、低耦合,避免一个类承担过多职责,提高代码的可读性、可维护性。

违反的表现

一个类或方法承担多个不同的功能,需要经常修改多个部分。

如何优化

拆分为多个职责单一的类或方法,每个类/方法只负责一件事。

好处

代码更清晰、可读性更高、易扩展、易测试、低耦合。

记住:一个类应该只有一个原因被修改!

3. 什么是开放-封闭原则?

3.1. 开放-封闭原则定义

定义:软件实体(类、模块、函数等)应该 对扩展开放,对修改封闭

  • 对扩展开放(Open for extension):可以通过增加新功能来扩展现有代码的行为。
  • 对修改封闭(Closed for modification):不应该修改已有代码来实现新需求,避免影响已有功能。

👉 目标:提高代码的可扩展性稳定性,避免因修改老代码导致新 Bug。

3.2. 为什么要遵循 OCP?

减少代码变更:修改老代码容易引入 Bug,遵循 OCP 可以降低维护成本。
提高系统稳定性:不修改现有代码,避免影响已有功能。
增强可扩展性:新需求可以通过新增代码实现,而不是修改老代码。

3.3. 示例:如何应用 OCP?

3.3.1. 不遵循 OCP(错误示范)

假设我们有一个计算不同形状面积的方法:

public class AreaCalculator {public double calculateArea(Object shape) {if (shape instanceof Circle) {Circle c = (Circle) shape;return Math.PI * c.getRadius() * c.getRadius();} else if (shape instanceof Rectangle) {Rectangle r = (Rectangle) shape;return r.getWidth() * r.getHeight();}return 0;}
}

问题:

  • 每次增加新的形状(如 Triangle),都要修改 calculateArea() 方法。
  • 违反 OCP,因为要修改原来的代码,风险高,代码不稳定。

3.3.2. 遵循 OCP(正确示范 - 使用多态)

可以使用 抽象类 + 继承 让系统支持扩展,而不修改原有代码:

// 1. 创建 Shape 抽象类
abstract class Shape {public abstract double calculateArea();
}// 2. 具体形状实现各自的计算逻辑
class Circle extends Shape {private double radius;public Circle(double radius) { this.radius = radius; }public double getRadius() { return radius; }@Overridepublic double calculateArea() {return Math.PI * radius * radius;}
}class Rectangle extends Shape {private double width, height;public Rectangle(double width, double height) { this.width = width; this.height = height; }@Overridepublic double calculateArea() {return width * height;}
}// 3. 计算面积的方法
public class AreaCalculator {public double calculateArea(Shape shape) {return shape.calculateArea();}
}

好处:新增形状(如 Triangle)时,不需要修改 AreaCalculator 代码,只需要新增一个 Triangle 类即可:

class Triangle extends Shape {private double base, height;public Triangle(double base, double height) { this.base = base; this.height = height; }@Overridepublic double calculateArea() {return 0.5 * base * height;}
}

🔹 这样我们扩展了新功能,但没有修改 AreaCalculator,符合 OCP!

3.4. 其他 OCP 实现方式

除了继承 + 多态,还有:

  1. 使用接口
interface Payment {void pay(double amount);
}class WeChatPay implements Payment {public void pay(double amount) {System.out.println("使用微信支付:" + amount + " 元");}
}class AliPay implements Payment {public void pay(double amount) {System.out.println("使用支付宝支付:" + amount + " 元");}
}
  1. 扩展新支付方式(如 ApplePay),无需修改老代码,符合 OCP!
  2. 使用策略模式(Strategy Pattern):适用于有多种行为可扩展的情况(比如不同的折扣策略、支付方式)。

3.5. 什么时候使用 OCP?

  • 系统需求变更频繁(避免频繁修改老代码导致 Bug)。
  • 需要支持多种类型的行为(如不同形状、不同支付方式)。
  • 核心业务逻辑比较稳定,但可能会增加新功能

4. 泛型原理与示例

是的,泛型(Generics) 是 Java 中的一种特性,允许我们编写通用的、类型安全的代码。泛型的主要目的是在编译时提供类型检查,避免强制类型转换带来的问题,同时提高代码的复用性。

4.1. 泛型的基本用法

4.1.1. 泛型类

可以在类定义时指定泛型:

public class Box<T> {private T value;public void setValue(T value) {this.value = value;}public T getValue() {return value;}
}

使用时,可以为 T 指定具体类型:

Box<String> stringBox = new Box<>();
stringBox.setValue("Hello");
System.out.println(stringBox.getValue()); // HelloBox<Integer> intBox = new Box<>();
intBox.setValue(123);
System.out.println(intBox.getValue()); // 123

4.1.2. 泛型方法

除了泛型类,还可以定义泛型方法

public class Util {// 这里泛型表示入参是一个泛型,表示可以传递类型数组(可以是String、Integer、其他类型)public static <T> void printArray(T[] array) {for (T item : array) {System.out.print(item + " ");}System.out.println();}
}

使用泛型方法:

String[] words = {"Hello", "World"};
Integer[] numbers = {1, 2, 3};Util.printArray(words);   // Hello World
Util.printArray(numbers); // 1 2 3

4.1.3. 泛型接口

可以让接口使用泛型:

//泛型接口
public interface Storage<T> {void add(T item);T get(int index);
}

实现接口时指定具体类型:

public class StringStorage implements Storage<String> {private List<String> list = new ArrayList<>();public void add(String item) {list.add(item);}public String get(int index) {return list.get(index);}
}

4.1.4. 泛型通配符 ?

当不确定具体类型时,可以使用 ? 作为通配符:

public static void printList(List<?> list) {for (Object item : list) {System.out.println(item);}
}

List<?> 表示可以接收任何类型的 List

List<String> strList = Arrays.asList("A", "B", "C");
List<Integer> intList = Arrays.asList(1, 2, 3);printList(strList);
printList(intList);

💡 注意:List<?> 不能添加元素,因为 Java 不能确定它的实际类型,只能读取。

4.1.5. 限定类型(extendssuper

4.1.5.1. 上界通配符 <? extends T>

如果只需要读取数据,可以使用 ? extends T,表示接受 T 及其子类:

public static void readList(List<? extends Number> list) {for (Number num : list) {System.out.println(num);}
}

可传入 List<Integer>List<Double>

List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);readList(intList);
readList(doubleList);

💡 特点

  • 可以读取数据(Number 或其子类)。
  • 不能添加数据(除了 null)。
4.1.5.2. 下界通配符 <? super T>

如果只需要写入数据可以使用 ? super T,表示接受 T 及其父类:

java复制编辑
public static void addNumbers(List<? super Integer> list) {list.add(10);list.add(20);
}

可传入 List<Integer>List<Number>List<Object>

java复制编辑
List<Number> numberList = new ArrayList<>();
addNumbers(numberList);
System.out.println(numberList); // [10, 20]

💡 特点

  • 可以添加 Integer 及其子类数据。
  • 读取时只能当作 Object 处理

4.2. 泛型的限制

  1. 泛型不能用于基本数据类型
List<int> list = new ArrayList<>(); // ❌ 错误

需要使用包装类型

List<Integer> list = new ArrayList<>(); // ✅ 正确
  1. 不能创建泛型数组
T[] array = new T[10]; // ❌ 错误

需要使用 Object[] 代替:

Object[] array = new Object[10]; // ✅ 正确
  1. 不能实例化泛型类型
public class Box<T> {T instance = new T(); // ❌ 错误
}

需要使用构造方法传递

public class Box<T> {private T instance;public Box(Class<T> clazz) throws Exception {this.instance = clazz.getDeclaredConstructor().newInstance();}
}

4.3. 泛型总结

特性

泛型的作用

类型安全

通过编译时检查,避免 ClassCastException

代码复用

相同逻辑可适用于不同的数据类型

可读性提高

代码更清晰,无需强制类型转换

性能优化

避免不必要的类型检查,提高运行效率

泛型是 Java 通用编程的强大工具,可以在类、方法、接口等场景中使用,提升代码的安全性、复用性和可维护性。🚀

5. 在编写接口时,选择泛型还是具体类型?

在编写接口时,选择泛型还是具体类型,主要取决于以下几个因素:

  1. 是否需要增强通用性(支持不同的数据类型)
  2. 是否需要约束返回值或参数类型(限制为某种具体类型)
  3. 接口的使用场景(是否依赖于特定业务逻辑)

5.1. 什么时候使用泛型?

如果接口需要适用于多种类型,且不依赖于具体实现,就应该使用泛型,这样可以提高代码的通用性和复用性

5.1.1. 泛型适用于以下情况:

  • 接口支持多种数据类型
  • 不关心具体的实现类
  • 希望增强代码的灵活性和复用性
  • 返回值或参数的类型由调用者决定

5.1.2. 示例 1:通用存储接口

public interface Repository<T> {void save(T entity);T findById(int id);
}

这样,Repository<T> 可以用于任何数据类型:

class User {}
class Product {}Repository<User> userRepo = new UserRepository();
Repository<Product> productRepo = new ProductRepository();

好处:

  • UserRepositoryProductRepository 可以共用 Repository<T> 逻辑。
  • save(T entity) 保证了存入的对象类型安全。

5.1.3. 示例 2:泛型方法

有时候,方法本身可以使用泛型,而不是整个接口:

public interface Converter {<T> T convert(String input, Class<T> clazz);
}

这样可以支持不同类型的转换:

Converter converter = new StringConverter();
Integer num = converter.convert("123", Integer.class);
Double d = converter.convert("12.34", Double.class);

5.2. 什么时候使用具体的实例类?

如果接口的输入或输出只涉及固定的业务逻辑,且不需要支持多种类型,就应该使用具体类型

5.2.1. 具体类型适用于以下情况:

  • 接口逻辑只适用于特定数据类型
  • 接口方法需要操作具体的字段
  • 返回值必须是固定的类型

5.2.2. 示例 1:固定业务逻辑的接口

public interface UserService {void register(User user);User findById(int id);
}

这里 UserService 只针对 User,不会用于其他类型,因此不需要泛型。

5.2.3. 示例 2:固定返回值

public interface PaymentService {PaymentResult processPayment(PaymentRequest request);
}

这里 processPayment 方法总是返回 PaymentResult,不会返回其他类型,所以不需要泛型。

5.3. 泛型 vs 具体类型对比

对比项

使用泛型(T)

使用具体类型

适用场景

需要支持多种类型

仅适用于特定类型

灵活性

高,可扩展

低,局限于特定类型

代码复用

代码可复用

代码可能重复

安全性

编译时检查类型

仅适用于特定类型

典型示例

List<T>

, Repository<T>

UserService

, PaymentService

5.4. 设计决策总结

使用泛型(通用、公共方法,不涉及业务逻辑

  • 如果接口适用于多个类型,且与具体类型无关(如 Repository<T>
  • 如果返回值或参数类型可以变化(如 Converter
  • 如果方法或接口需要提供通用能力(如 List<T>

使用具体类型(涉及业务相关使用的具体实现类)

  • 如果接口逻辑特定于某个实体(如 UserService
  • 如果方法返回值不需要变化(如 PaymentService
  • 如果接口涉及特定领域业务逻辑(如 OrderProcessor

博文参考

相关文章:

系统设计——项目设计经验总结1

摘要 在系统设计的时候&#xff0c;注意域的区分&#xff0c;功能区分、类的区分、方法区分范围和定义。在系统设计的时候的&#xff0c;需要思考类、方法在什么情况下会涉及到修改&#xff0c;遵循记住&#xff1a;一个类应该只有一个原因被修改&#xff01; 当不满足&#x…...

如何在WordPress网站上添加即时聊天功能

在 WordPress 网站上添加即时聊天功能既简单又有益。近年来&#xff0c;即时聊天已经有了长足的发展&#xff0c;融入了强大的交流和自动化功能&#xff0c;类似于流行的人工智能聊天机器人。无论您是想提高销售转化率还是将人工智能整合到客户服务流程中&#xff0c;在 WordPr…...

[luogu12542] [APIO2025] 排列游戏 - 交互 - 博弈 - 分类讨论 - 构造

传送门&#xff1a;https://www.luogu.com.cn/problem/P12542 题目大意&#xff1a;给定一个长为 n n n 的排列和一张 m m m 个点 e e e 条边的简单连通图。每次你可以在图上每个点设置一个 0 ∼ n − 1 0\sim n-1 0∼n−1、两两不同的权值发给交互库&#xff0c;交互库会…...

图像处理基础知识

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 信息是自然界物质运动总体的一个重要方面&#xff0c;人们认识世界和改造世界就是要获得各种各样的图像信息&#xff0c;这些信息是人类获得外界信息的主要来源。大约有70%的信息是通过人眼获得的。近代科学研…...

使用MybatisPlus实现sql日志打印优化

背景&#xff1a; 在排查无忧行后台服务日志时&#xff0c;一个请求可能会包含多个执行的sql&#xff0c;经常会遇到SQL语句与对应参数不连续显示&#xff0c;或者参数较多需要逐个匹配的情况。这种情况下&#xff0c;如果需要还原完整SQL语句就会比较耗时。因此&#xff0c;我…...

HarmonyOS5云服务技术分享--ArkTS开发Node环境

✨ 你好呀&#xff0c;开发者小伙伴们&#xff01;今天我们来聊聊如何在HarmonyOS&#xff08;ArkTS API 9及以上&#xff09;中玩转云函数&#xff0c;特别是结合Node.js和HTTP触发器的开发技巧。文章会手把手带你从零开始&#xff0c;用最接地气的方式探索这个功能&#xff0…...

水利数据采集MCU水资源的智能守护者

水利数据采集仪MCU&#xff0c;堪称水资源的智能守护者&#xff0c;其重要性不言而喻。在水利工程建设和水资源管理领域&#xff0c;MCU数据采集仪扮演着不可或缺的角色。它通过高精度的传感器和先进的微控制器技术&#xff0c;实时监测和采集水流量、水位、水质等关键数据&…...

深度学习之用CelebA_Spoof数据集搭建一个活体检测-用MNN来推理时候如何利用Conan对软件包进行管理

我为什么用Conan 前面的文章&#xff1a;深度学习之用CelebA_Spoof数据集搭建一个活体检测-训练好的模型用MNN来推理有提到怎么使用MNN对训练好的模型进行推理&#xff0c;里面并没有提到我是怎么编译和进行代码依赖包的管理的详细步骤&#xff0c;在这里我是用的是Conan:一个…...

深入解剖 G1 收集器的分区模型与调优策略

JVM 垃圾收集系列之三 | 高并发低延迟系统的首选 GC 解法&#xff01; 一、为什么我们需要 G1 垃圾收集器&#xff1f; 在传统 GC&#xff08;如 CMS&#xff09;中&#xff0c;我们常常面临的问题是&#xff1a; GC 停顿不可预测&#xff08;Stop-The-World&#xff09;内存…...

兰亭妙微・UI/UX 设计・全链路开发

【遇见专业设计&#xff0c;共筑卓越产品】 在数字化浪潮中&#xff0c;界面是产品与用户对话的第一窗口。 兰亭妙微&#xff08;蓝蓝设计&#xff09;&#xff0c;自 2008 年深耕 UI/UX 领域&#xff0c;以清华团队为核心&#xff0c;16 年专注软件与互联网产品的界面设计开…...

Babylon.js学习之路《六、材质与纹理:为模型赋予真实的表面效果》

文章目录 1. 引言&#xff1a;材质与纹理的重要性1.1 材质与纹理的核心作用 2. 基础材质&#xff1a;StandardMaterial2.1 材质属性详解2.2 实战&#xff1a;创建金属材质 3. 纹理贴图&#xff1a;从基础到高级3.1 基础纹理映射3.2 多纹理混合技术 4. 高级材质&#xff1a;PBRM…...

飞致云旗下开源项目GitHub Star总数突破150,000个

2025年5月19日&#xff0c;中国领先的开源软件提供商飞致云宣布&#xff0c;其旗下开源项目在代码托管平台GitHub上所获得的Star总数已经超过150,000个。基于在开源领域的长期耕耘和探索&#xff0c;飞致云的开源势能不断增强&#xff0c;获得第一个五万GitHub Star用时89个月&…...

萌新联赛第(三)场

C题 这道题用暴力去写想都不要想&#xff0c;一定超时&#xff0c;于是我们需要优化&#xff0c;下面是思路过程&#xff1a; 如图&#xff0c;本题只需找到x的因数个数和(n-x)的因数个数&#xff0c;这两个相乘&#xff0c;得到的就是对于这个x来说组合的个数&#xff0c;且x…...

cplex12.9 安装教程以及下载

cplex 感觉不是很好找&#xff0c;尤其是教育版&#xff0c;我这里提供一个版本&#xff0c;在下面的图可以看到&#xff0c;不仅可以配置matlab&#xff0c;也可以配置vs,现在拿vs2017来测试一下&#xff0c;具体文件的文件有需要的可以复制下面的链接获取 我用网盘分享了「c…...

Pycharm-jupyternotebook不渲染

解决方案&#xff1a; https://youtrack.jetbrains.com/issue/PY-54244 import plotly.io as pio pio.renderers.default "vscode"...

layui 介绍

layui&#xff08;谐音&#xff1a;类 UI) 是一套开源的 Web UI 解决方案&#xff0c;采用自身经典的模块化规范&#xff0c;并遵循原生 HTML/CSS/JS 的开发方式&#xff0c;极易上手&#xff0c;拿来即用。其风格简约轻盈&#xff0c;而组件优雅丰盈&#xff0c;从源代码到使用…...

大数据相关操作

大数据相关操作 一、环境配置 1、修改主机名 #修改主机名 hostnamectl set-hostname master2、固定IP地址 # 进入修改 sudo vim /etc/netplan/01-network-manager-all.yaml# 修改配置文件 # Let NetworkManager manage all devices on this system network:version: 2rend…...

谷歌宣布推出 Android 的新安全功能,以防止诈骗和盗窃

在上周二的 Android Show 上&#xff0c;也就是Google I/O 开发者大会之前&#xff0c;谷歌宣布了 Android 的全新安全和隐私功能。这些新功能包括对通话、屏幕共享、消息、设备访问和系统级权限的全新保护。谷歌希望通过这些功能保护用户免遭诈骗&#xff0c;在设备被盗或被攻…...

WSL虚拟机整体迁移教程(如何将WSL从C盘迁移到其他盘)

文章目录 WSL虚拟机迁移教程一、查看当前主机的子系统二、导出 WSL 子系统三、将打包好的文件发送给另一个人四、在另一台机器导入并恢复子系统五、附加命令六、注意事项和导出文件信息6.1 注意事项6.2 导出文件信息使用 wsl --export 命令导出整个 WSL 子系统时&#xff0c;它…...

汽车区域电子电气架构(Zonal E/E)的统一

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 钝感力的“钝”&#xff0c;不是木讷、迟钝&#xff0c;而是直面困境的韧劲和耐力&#xff0c;是面对外界…...

开源一个记账软件,支持docker一键部署

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 开源一个记账软件&#xff0c;支持docker一键部署 项目简介功能特性技术栈快速开始环境要求运行步…...

新能源汽车焊接智能节气阀

在新能源汽车产业迅猛发展的浪潮中&#xff0c;制造工艺的优劣直接关系到车辆的性能、安全与市场竞争力。焊接&#xff0c;作为新能源汽车生产流程里的关键一环&#xff0c;无论是构建车身框架&#xff0c;还是连接电池模组&#xff0c;其质量的好坏都起着决定性作用。而在焊接…...

React 第四十四节Router中 usefetcher的使用详解及注意事项

前言 useFetcher 是 React Router 中一个强大的钩子&#xff0c;用于在不触发页面导航的情况下执行数据加载&#xff08;GET&#xff09;或提交&#xff08;POST&#xff09;。 一、useFetcher 应用场景&#xff1a; 1、后台数据预加载&#xff08;如鼠标悬停时加载数据&…...

33、魔法防御术——React 19 安全攻防实战

一、奥术护盾&#xff08;基础防御&#xff09; 1. 敏感数据加密术 // cryptoUtils.js - 数据加密工具export const encrypt (data) > {// 实际项目应使用Web Crypto API或crypto-jsreturn btoa(encodeURIComponent(data));};​export const decrypt (data) > {try {…...

NVM 安装与配置指南

简介 Node Version Manager&#xff08;NVM&#xff09;是一个常用的 Node.js 版本管理工具&#xff0c;可用于在开发过程中方便地切换不同版本的 Node.js。通过 NVM&#xff0c;用户可以根据项目需求选择不同的 Node.js 版本&#xff0c;而无需手动安装和卸载多个版本的 Node…...

SpringMVC04所有注解按照使用位置划分| 按照使用层级划分(业务层、视图层、控制层)

目录 一、所有注解按照使用位置划分&#xff08;类、方法、参数&#xff09; 1. 类级别注解 2. 方法级别注解 3. 参数级别注解 4. 字段/返回值注解 二、按照使用层级划分&#xff08;业务层、视图层、控制层&#xff09; 1、控制层&#xff08;Controller Layer&#x…...

【数据库】-1 mysql 的安装

文章目录 1、mysql数据库1.1 mysql数据库的简要介绍 2、mysql数据库的安装2.1 centos安装2.2 ubuntu安装 1、mysql数据库 1.1 mysql数据库的简要介绍 MySQL是一种开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由瑞典MySQL AB公司开发&#xff0c;目前…...

MySQL与Redis一致性问题分析

一、一致性问题概述 1.1 什么是一致性问题&#xff1f; 在数据库-缓存架构中&#xff0c;当MySQL中的数据&#xff08;最新值&#xff09;与Redis缓存中的数据&#xff08;缓存旧值&#xff09;出现差异时&#xff0c;由于程序总是优先读取Redis缓存&#xff0c;就会导致应用…...

Xshell传输文件

新建文件 点击新建 完善主机地址 然后输入我们的远端服务器的SSH协议 一般的是这样的ssh -p 44562 rootregion-1.autodl.com 由于Xshell比较特殊我们输入ssh rootregion-1.autodl.com 44562这样的形式 然后输入服务器的密码即可...

怎样用 esProc 为大主子表关联提速

类似订单和明细表这样的主子表关联比较常见&#xff0c;在 SQL 中&#xff0c;这种关联用 JOIN 实现&#xff0c;在两个表都很大的情况下&#xff0c;常常出现计算速度非常慢的现象。 如果预先将主子表都按照主键有序存储&#xff0c;就可以使用归并算法实现关联。这种算法只需…...

打卡day31

文件的规范拆分和写法 知识点回顾 规范的文件命名规范的文件夹管理机器学习项目的拆分编码格式和类型注解 作业&#xff1a;尝试针对之前的心脏病项目&#xff0c;准备拆分的项目文件&#xff0c;思考下哪些部分可以未来复用。 导入依赖库 # 忽视警告 import warnings warn…...

编译原理的部分概念

解释程序&#xff1a;边解释边执行&#xff1a;不断读取源程序的语句&#xff0c;解释语句&#xff0c;读取此语句需要的数据&#xff0c;根据执行结果读取下一条语句&#xff0c;继续解释执行&#xff0c;直到返回结果。 编译程序&#xff1a;将源程序完整地转换成机器语言程…...

Java中字符串(String类)的常用方法

以下是Java中字符串&#xff08;String类&#xff09;的常用方法分类详解&#xff0c;包含核心方法说明和示例代码&#xff1a; 一、字符串基础信息 方法说明示例输出length()返回字符串长度"Hello".length()5isEmpty()判断字符串是否为空&#xff08;长度是否为0&a…...

什么是 ERP,中国企业如何科学应用 ERP

中国企业在引入 ERP 系统过程中&#xff0c;常因盲目跟风大型企业选型、忽视自身业务适配性&#xff0c;导致系统功能过剩、实施成本高企、员工接受度低等问题&#xff0c;最终造成项目成功率不足 10%。因此&#xff0c;理性认知 ERP 的价值定位与本土化实施路径&#xff0c;成…...

使用SQLite Expert个人版VACUUM功能修复数据库

使用SQLite Expert个人版VACUUM功能修复数据库 一、SQLite Expert工具简介 SQLite Expert 是一款功能强大的SQLite数据库管理工具&#xff0c;分为免费的个人版&#xff08;Personal Edition&#xff09;和收费的专业版&#xff08;Professional Edition&#xff09;。其核心功…...

同源策略深度防御指南:CSP 高级应用与企业微信全场景适配(含 report-uri 实战)

一、CSP 核心指令权威解析与企业微信适配 内容安全策略&#xff08;CSP&#xff09;通过Content-Security-Policy响应头实现资源加载的细粒度控制&#xff0c;其核心指令与企业微信场景强相关&#xff1a; 1.1 frame-ancestors&#xff1a;iframe 嵌入源控制 权威规范&#…...

【AGI】大模型微调技术-四大微调框架

【AGI】大模型微调技术-四大微调框架 &#xff08;1&#xff09;微调基础概念介绍1.1 微调基本概念1.2 全量微调与高效微调1.3 模型微调的优劣势分析1.4 高效微调与LoRA、QLoRA &#xff08;2&#xff09;高效微调的应用场景&#xff08;3&#xff09;流微调工具介绍3.1 unslot…...

小白编程学习之巧解「消失的数字」

一、引言&#xff1a;一个看似简单的「找不同」问题 今天遇到一道有趣的算法题&#xff1a;给定一个含 n 个整数的数组 nums&#xff0c;其中每个元素都在 [1, n] 范围内&#xff0c;要求找出所有在 [1, n] 中但未出现在数组中的数字。 这让我想起小时候玩的「找错题」游戏 —…...

在 Git 中添加子模块(submodule)的详细步骤

在 Git 中添加子模块&#xff08;submodule&#xff09;的详细步骤如下&#xff1a; 1. 添加子模块 命令格式&#xff1a; git submodule add <仓库URL> [目标路径]仓库URL&#xff1a;子模块的 Git 仓库地址&#xff08;HTTP/SSH 均可&#xff09;。目标路径&#xff…...

瑞萨单片机笔记

1.CS for CC map文件中显示变量地址 Link Option->List->Output Symbol information 2.FDL库函数 pfdl_status_t R_FDL_Write(pfdl_u16 index, __near pfdl_u08* buffer, pfdl_u16 bytecount) pfdl_status_t R_FDL_Read(pfdl_u16 index, __near pfdl_u08* buffer, pfdl_…...

单片机复用功能重映射Remap功能

目录 一、查看“DS5319 stm32f10x中等密度mcu数据手册&#xff08;英文&#xff09;”手册 二、查看“RM0008 STM32F10xxx参考手册&#xff08;中文&#xff09;”手册 三、重映射&#xff08;Remap&#xff09;功能程序编写 自己学习过程中容易遗忘的知识点&#xff0c;记录…...

小白入门FPGA设计,如何快速学习?

很多刚入门的小伙伴&#xff0c;初次听说FPGA&#xff08;现场可编程门阵列&#xff09;&#xff0c;脑子里只有一个字&#xff1a;玄&#xff01; 什么“时序逻辑”“Verilog”“Vivado”&#xff0c;仿佛一夜之间掉进了电子黑魔法的深坑。 但真相是—— FPGA&#xff0c;其实…...

友思特应用 | LCD显示屏等玻璃行业的OCT检测应用

导读 光学相干层析成像(OCT)是一种非侵入式光学成像方法&#xff0c;提供微米尺度的空间分辨率&#xff0c;能够生成内部结构截面图像。自20世纪90年代初发明第一台OCT以来&#xff0c;它在眼科领域得到了广泛应用&#xff0c;并成为临床诊断的黄金标准之一。除了在生物医学领…...

Python的sys模块:系统交互的关键纽带

Python的sys模块&#xff1a;系统交互的关键纽带 对话实录 小白&#xff1a;&#xff08;挠头&#xff09;我知道 Python 能做很多事&#xff0c;可怎么让它和计算机系统‘交流’呢&#xff0c;比如获取系统信息、处理命令行参数&#xff1f; 专家&#xff1a;&#xff08;微…...

若依项目集成sentinel、seata和shardingSphere

集成组件包括MySQL分库分表及读写分离、seata以及Sentinel 若依项目文档连接 代码下载地址 需要结合ruoyi代码配合看&#xff0c;前提是熟悉基本代码结构&#xff0c;熟悉feign调用和基础网关配置等。 采用的版本信息 <java.version>1.8</java.version> <spr…...

张 推进对话式心理治疗:SOULSPEAK的聊天机器人

SOULSPEAK的聊天机器人 利用大语言模型(LLM)来提供低成本的心理治疗服务,旨在解决传统心理咨询在隐私、成本和可及性方面的不足。以下是核心内容的通俗解读: 1. 研究背景:传统心理治疗的困境 问题:全球心理健康问题日益严重(如焦虑、抑郁人数激增),但传统心理咨询受…...

java中的Filter使用详解

Filter&#xff08;过滤器&#xff09;是 Java Web 开发的核心组件之一&#xff0c;用于在请求到达 Servlet 或响应返回客户端之前进行拦截和处理。以下是其核心功能、使用方法和实际场景的详细解析&#xff1a; 一、Filter 的作用与原理 核心作用 Filter 充当请求与响应之间的…...

BERT 作为Transformer的Encoder 为什么采用可学习的位置编码

摘要 BERT 在位置编码上与原始 Transformer 论文中的 sin/cos 公式不同&#xff0c;选择了可学习&#xff08;learned&#xff09;的位置嵌入方案。本文将从 Transformer 原始位置编码选项入手&#xff0c;分析 BERT 选择 learned positional embeddings 的四大核心原因&#x…...

Vue百日学习计划Day43-45天详细计划-Gemini版

Day 43: Composable 函数基础与抽取简单逻辑 (~3 小时) 本日目标: 理解 Composable 函数的概念、优势&#xff0c;并学会如何将简单的、无状态的逻辑抽取为 Composable。所需资源: Vue 3 官方文档 (组合式函数): https://cn.vuejs.org/guide/reusability/composables.html 学…...

Kotlin 协程 (二)

Kotlin 协程提供了丰富的功能&#xff0c;能够高效地处理并发和异步任务。以下是对 Kotlin 协程中常见概念和功能的详细讲解&#xff0c;包括它们的定义、作用、使用场景以及最佳实践。 1. 协程核心概念 1.1 CoroutineScope 定义&#xff1a;CoroutineScope 是协程作用域的抽…...