系統設計——項目設計經驗總結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.pswp.cn/pingmian/81680.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81680.shtml
英文地址,請注明出處:http://en.pswp.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;并且解決問題。 【注】 這個問題出…