系统设计——项目设计经验总结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

博文参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/81680.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java高阶面经:微服务篇】3.熔断机制深度优化:从抖动治理到微服务高可用架构实战

一、熔断抖动的本质剖析与核心成因 1.1 熔断机制的核心价值与抖动危害 熔断机制作为微服务弹性架构的核心组件,通过模拟电路断路器逻辑,在服务出现异常时自动阻断请求链,防止故障扩散引发雪崩。但频繁的“熔断-恢复-熔断”抖动会导致: 用户体验恶化:请求成功率波动大,响…

深入浅出人工智能:机器学习、深度学习、强化学习原理详解与对比!

各位朋友&#xff0c;大家好&#xff01;今天咱们聊聊人工智能领域里最火的“三剑客”&#xff1a;机器学习 (Machine Learning)、深度学习 (Deep Learning) 和 强化学习 (Reinforcement Learning)。 听起来是不是有点高大上&#xff1f; 别怕&#xff0c;我保证把它们讲得明明…

【动手学深度学习】1.1~1.2 机器学习及其关键组件

目录 一、引言1.1. 日常生活中的机器学习1.2. 机器学习中的关键组件1&#xff09;数据2&#xff09;模型3&#xff09;目标函数4&#xff09;优化算法 一、引言 1.1. 日常生活中的机器学习 应用场景&#xff1a; 以智能语音助手&#xff08;如Siri、Alexa&#xff09;的唤醒…

Pytorch针对不同电脑配置详细讲解+安装(CPU)

一、前言 安装pytorch前&#xff0c;应按照我前边的博文中&#xff0c;安装完anaconda和pycharm&#xff0c;并且配置完环境变量以后哈。 Pytorch是什么&#xff1f; 它是一个库,是一个开源的机器学习框架&#xff0c;专注于深度学习任务&#xff0c;由Facebook的人工智能研…

[python] 轻量级定时任务调度库schedule使用指北

schedule是一款专为简化定时任务调度而设计的Python库&#xff0c;它通过直观的语法降低了周期性任务的实现门槛。作为进程内调度器&#xff0c;它无需额外守护进程&#xff0c;轻量且无外部依赖&#xff0c;适合快速搭建自动化任务。不过&#xff0c;该库在功能完整性上有所取…

React的合成事件(SyntheticEventt)

文章目录 前言 前言 React的合成事件&#xff08;SyntheticEvent&#xff09;是React为了统一不同浏览器的事件处理行为而封装的一套跨浏览器事件系统。它与原生事件的主要区别如下&#xff1a; 1. 事件绑定方式 • 合成事件&#xff1a;使用驼峰命名法绑定事件&#xff08;如…

报表控件stimulsoft教程:如何在报表和仪表板中创建热图

Stimulsoft Ultimate &#xff08;原Stimulsoft Reports.Ultimate&#xff09;是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能&#xff0c;Stimulsoft Ultimate包含了…

[免费]苍穹微信小程序外卖点餐系统修改版(跑腿点餐系统)(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序医院预约挂号管理系统(uni-appSpringBoot后端Vue管理端)&#xff0c;分享下哈。 项目视频演示 【免费】苍穹微信小程序外卖点餐系统修改版(跑腿点餐系统)(SpringBoot后端Vue管理端) Java毕业设计…

Dify 快速上手 MCP!Java 搭建 MCP Server 接入 Dify详细实战攻略

近期&#xff0c;MCP协议在AI领域热度飙升&#xff0c;成为众多开发者和行业人士热议的焦点。下文先介绍MCP究竟是什么&#xff1f;再详细讲下 Dify DeepSeek Java开发 MCP server 实战。 一、MCP的基本概念 MCP&#xff0c;全称为模型上下文协议&#xff08;Model Context P…

力扣992做题笔记

左神做法的理论依据 我们可以通过 集合的包含关系 和 具体示例枚举 来直观理解这一推导过程。以下结合题目示例 1 进行详细说明&#xff1a; 示例 1 分析 输入&#xff1a;nums [1,2,1,2,3], k 2 目标&#xff1a;计算恰好包含 2 种不同整数 的子数组个数。 步骤一集合 A…

Kubernetes 运维操作手册:从 etcd 快照进行精确恢复

1 5 步实现 etcd 精确恢复 将快照恢复到本地 etcd 数据目录。使用恢复的数据启动本地 etcd 实例。使用 etcdctl 查询特定键&#xff08;例如&#xff0c;ConfigMap&#xff09;。使用 auger 解码以提取干净的 YAML。使用 kubectl 申请恢复到您的实时集群。 本指南将指导您从 et…

LeetCode Hot100刷题——合并区间

56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;i…

《Metasploit框架核心模块解析与安全防护实践》​

目录 ​​一、框架模块化设计与安全验证价值​​ ​​1. 漏洞验证模块&#xff08;Exploit Modules&#xff09;​​ ​​2. 安全评估模块&#xff08;Auxiliary Modules&#xff09;​​ ​​3. 安全响应模块&#xff08;Post-Exploitation&#xff09;​​ ​​4. 载荷安全…

Cribl 中 Parser 扮演着重要的角色 + 例子

先看文档: Parser | Cribl Docs Parser The Parser Function can be used to extract fields out of events or reserialize (rewrite) events with a subset of fields. Reserialization will preserve the format of the events. For example, if an event contains comma…

程序设计实践--排序(1)

&#xff11;、插入排序&#xff08;一个数组&#xff09; #include<bits/stdc.h> using namespace std; const int N1e35; int a[N]; int n; int main(){cin>>n;for(int i1;i<n;i){cin>>a[i];}for(int i1;i<n;i){int va[i];int ji-1;while(j>1&am…

MAC电脑中右键后复制和拷贝的区别

在Mac电脑中&#xff0c;右键菜单中的“复制”和“拷贝”操作在功能上有所不同&#xff1a; 复制 功能&#xff1a;在选定的位置创建一个与原始文件相同的副本。快捷键&#xff1a;CommandD用于在当前位置快速复制文件&#xff0c;CommandC用于将内容复制到剪贴板。效果&…

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

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

Linux:面试题

1. 什么是中断和异常&#xff1f; 中断&#xff1a;由外部设备&#xff08;如键盘、网卡&#xff09;触发的异步事件&#xff0c;用于通知 CPU 有紧急事件需要处理。 异常&#xff1a;由 CPU 内部执行指令时产生的同步事件&#xff08;如除零错误、缺页异常&#xff09;&#…

linux关闭某端口暂用的进程

查看是哪个端口暂用 sudo netstat -tulpn | grep :80根据图片 显示 80端口暂用的 进程id是 3002 结束进程id为3002的进程 sudo kill -9 3002

【学习心得】Jupyter 如何在conda的base环境中其他虚拟环境内核

如果你在conda的base环境运行了jupyter lab打开了一个ipynb文本&#xff0c;此时选择的内核是base虚拟环境的Python内核&#xff0c;如果我想切换成其他conda虚拟环境来运行这个文件该怎么办&#xff1f;下面我们试着还原一下问题&#xff0c;并且解决问题。 【注】 这个问题出…