深入解析原型模式:從理論到實踐的全方位指南

深入解析原型模式:從理論到實踐的全方位指南

在這里插入圖片描述

引言:為什么需要原型模式?

在軟件開發過程中,對象創建是一個頻繁且關鍵的操作。傳統方式(如直接使用new關鍵字)在某些場景下會顯得效率低下且不夠靈活。想象這樣一個場景:我們需要創建10只屬性完全相同的羊,每只羊都有姓名(如"tom")、年齡(如1歲)和顏色(如白色)等屬性。按照常規做法,我們需要反復調用構造函數并設置相同的屬性值,這不僅代碼冗余,而且當對象結構復雜時,會顯著影響性能。

這正是原型模式(Prototype Pattern)大顯身手的地方。原型模式是一種創建型設計模式,它通過復制現有對象(稱為原型)來創建新對象,而不是通過新建類實例的方式。這種方式特別適合以下場景:

  • 當創建對象的過程復雜或代價高昂時
  • 當系統需要獨立于其產品的創建、組合和表示時
  • 當需要避免使用與產品層次結構平行的工廠類層次結構時
  • 當一個類的實例只能有幾個不同狀態組合中的一種時

本文將全面剖析原型模式的各個方面,包括其定義、原理、實現方式、在Spring框架中的應用、深淺拷貝的區別以及實際開發中的注意事項。

原型模式的定義與核心思想

基本概念

原型模式是指用原型實例指定創建對象的種類,并且通過拷貝這些原型來創建新的對象。這種模式屬于創建型設計模式,它允許一個對象再創建另外一個可定制的對象,而無需知道創建的細節。

用更形象的方式理解:就像《西游記》中孫大圣拔出猴毛,變出其他孫大圣一樣,原型模式通過"克隆"現有對象來生成新對象。這種"克隆"能力使得系統可以:

  1. 動態加載類
  2. 動態創建對象
  3. 避免重復初始化過程
  4. 保持對象狀態一致性

工作原理

原型模式的工作原理可以概括為:將一個原型對象傳給需要創建新對象的組件,這個組件通過請求原型對象拷貝自身來實施創建過程。在Java中,這通常通過調用對象的clone()方法實現。

具體來說,原型模式包含三個主要角色:

  1. Prototype(抽象原型類):聲明克隆自身的接口,通常是一個抽象類或接口
  2. ConcretePrototype(具體原型類):實現克隆操作的具體類
  3. Client(客戶端):通過調用原型對象的克隆方法來創建新對象

傳統創建方式的局限性

讓我們回到開頭的"克隆羊"問題。傳統方式創建10只相同屬性的羊存在以下缺點:

  1. 效率問題:每次創建新對象都需要重新獲取原始對象的屬性,當對象結構復雜時,效率較低
  2. 靈活性不足:總是需要重新初始化對象,而不是動態地獲得對象運行時的狀態
  3. 代碼冗余:需要重復編寫相同的屬性設置代碼
  4. 維護困難:當需要修改屬性時,必須在所有創建點進行修改
// 傳統方式創建10只相同的羊
List<Sheep> sheepList = new ArrayList<>();
for(int i=0; i<10; i++){Sheep sheep = new Sheep();sheep.setName("tom");sheep.setAge(1);sheep.setColor("白色");sheepList.add(sheep);
}

相比之下,原型模式通過克隆已有對象的方式,可以優雅地解決這些問題。

原型模式的UML結構與實現

UML類圖解析

原型模式的UML類圖清晰地展現了其核心結構:

https://i.imgur.com/xyz1234.png

  1. Prototype接口/抽象類
    • 聲明clone()方法
    • 作為所有具體原型類的父類
    • 定義克隆契約
  2. ConcretePrototype具體實現類
    • 實現clone()方法
    • 提供自我復制的具體邏輯
    • 可以有多個不同的具體實現
  3. Client客戶端
    • 維護一個原型實例
    • 通過調用原型實例的clone()方法創建新對象
    • 無需知道具體原型類的細節

在這里插入圖片描述

Java中的實現方式

在Java中,原型模式通常通過實現Cloneable接口并重寫Object類的clone()方法來實現。Cloneable是一個標記接口,表示該類支持克隆操作。

基本實現步驟如下:

  1. 實現Cloneable接口
  2. 重寫Object類的clone()方法
  3. clone()方法中調用super.clone()
  4. 根據需要處理深拷貝問題
// 羊類實現克隆功能
public class Sheep implements Cloneable {private String name;private int age;private String color;// 構造方法、getter和setter省略@Overrideprotected Object clone() {Sheep sheep = null;try {sheep = (Sheep)super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return sheep;}
}// 客戶端使用
public class Client {public static void main(String[] args) {Sheep originalSheep = new Sheep("tom", 1, "白色");// 克隆10只羊List<Sheep> sheepList = new ArrayList<>();for(int i=0; i<10; i++){Sheep clonedSheep = (Sheep)originalSheep.clone();sheepList.add(clonedSheep);}}
}

原型模式在Spring框架中的應用

Spring框架廣泛使用了原型模式來管理bean的生命周期。在Spring中,bean的作用域(scope)可以是單例(singleton)或原型(prototype)。當bean的作用域設置為prototype時,每次請求該bean都會創建一個新的實例。

配置方式:

<bean id="monster" class="com.example.Monster" scope="prototype"/>

或者使用注解方式:

@Scope("prototype")
@Component
public class Monster {// ...
}

Spring內部實現原型bean的關鍵代碼邏輯:

// 簡化版的Spring原型bean創建邏輯
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {// ...其他代碼if (mbd.isPrototype()) {// 處理原型作用域的beanObject prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBeanInstance(beanName, mbd, args);} finally {afterPrototypeCreation(beanName);}return prototypeInstance;}// ...其他代碼
}

Spring通過isPrototype()方法判斷當前bean是否為原型作用域,如果是,則每次都會創建一個新的實例。這種機制正是原型模式的典型應用。

深拷貝與淺拷貝:原型模式的核心問題

淺拷貝(Shallow Copy)詳解

淺拷貝是原型模式默認的拷貝方式,它具有以下特點:

  1. 對于基本數據類型的成員變量,直接進行值傳遞,復制屬性值給新對象
  2. 對于引用類型的成員變量,只復制引用值(內存地址),新舊對象共享同一實例
  3. 使用默認的clone()方法實現
  4. 實現簡單,效率高

以羊類為例,淺拷貝的實現:

public class Sheep implements Cloneable {private String name;    // String是不可變對象,可視為基本類型private int age;private String color;private Sheep friend;   // 引用類型成員@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();  // 默認實現是淺拷貝}
}

淺拷貝的問題在于,當對象包含引用類型成員時,克隆對象和原對象會共享這些成員。修改其中一個對象的引用成員,會影響另一個對象。

深拷貝(Deep Copy)詳解

深拷貝解決了淺拷貝的共享引用問題,它具有以下特點:

  1. 復制對象的所有基本數據類型的成員變量值
  2. 為所有引用數據類型的成員變量申請新的存儲空間
  3. 遞歸復制引用對象,直到整個對象圖都被復制
  4. 克隆對象與原對象完全獨立,互不影響

深拷貝可以通過兩種方式實現:

方式一:重寫clone方法實現深拷貝
public class Sheep implements Cloneable {private String name;private int age;private String color;private Sheep friend;@Overrideprotected Object clone() throws CloneNotSupportedException {Sheep clonedSheep = (Sheep)super.clone();if(this.friend != null) {clonedSheep.friend = (Sheep)this.friend.clone();}return clonedSheep;}
}
方式二:通過對象序列化實現深拷貝
public class DeepCopyUtil {@SuppressWarnings("unchecked")public static <T extends Serializable> T deepCopy(T object) {try {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(object);ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (T)ois.readObject();} catch (Exception e) {e.printStackTrace();return null;}}
}// 使用方式
Sheep original = new Sheep("tom", 1, "白色");
Sheep copy = DeepCopyUtil.deepCopy(original);

序列化方式實現深拷貝的優點是不需要手動處理每個引用字段,可以自動完成整個對象圖的深拷貝。但要求所有相關類都必須實現Serializable接口。

深淺拷貝的選擇策略

在實際開發中,選擇深拷貝還是淺拷貝應考慮以下因素:

  1. 對象復雜度:簡單對象可用淺拷貝,復雜對象圖建議深拷貝
  2. 性能要求:深拷貝代價更高,性能敏感場景需權衡
  3. 安全性需求:需要完全隔離對象狀態時,必須使用深拷貝
  4. 開發成本:深拷貝實現更復雜,維護成本更高

原型模式的最佳實踐與注意事項

適用場景

原型模式特別適用于以下場景:

  1. 創建成本高的對象:當創建新對象的成本較高(如需要進行大量計算或資源獲取)時,通過復制現有對象可以提高性能
  2. 避免使用子類工廠:當系統應該獨立于其產品的創建、組合和表示時,原型模式可以避免創建與產品層次結構平行的工廠類層次結構
  3. 運行時動態配置:當需要動態加載類或運行時確定實例化哪些類時
  4. 狀態保存與恢復:當需要保存和恢復對象狀態,同時又希望對外隱藏實現細節時
  5. 大量相似對象創建:如游戲開發中大量相同或相似敵人的創建,圖形編輯器中相同圖形的復制等

優點與價值

原型模式具有以下顯著優點:

  1. 性能提升:避免重復執行初始化代碼,特別是當初始化需要消耗大量資源時
  2. 動態性:可以在運行時動態添加或刪除產品,比靜態工廠方法更靈活
  3. 簡化創建結構:不需要專門的工廠類來創建產品,減少了類的數量
  4. 狀態保存:可以保存對象的狀態,方便后續恢復到某個歷史狀態
  5. 減少約束:某些語言中,構造函數有較多約束,而clone方法可以繞過這些限制

潛在問題與解決方案

盡管原型模式強大,但在使用時也需要注意以下問題:

  1. 深拷貝實現復雜
    • 問題:當對象引用關系復雜時,實現深拷貝可能很困難
    • 解決方案:考慮使用序列化方式實現深拷貝,或使用第三方庫如Apache Commons Lang中的SerializationUtils
  2. 違背開閉原則(OCP)
    • 問題:需要為每個類配備克隆方法,對已有類進行改造時需要修改源代碼
    • 解決方案:在設計初期就考慮克隆需求,或使用組合模式替代繼承
  3. 循環引用問題
    • 問題:對象圖中存在循環引用時,可能導致無限遞歸或棧溢出
    • 解決方案:使用特殊標記處理已拷貝對象,避免重復拷貝
  4. final字段問題
    • 問題:Java中final字段在clone后無法修改
    • 解決方案:在clone方法中重新初始化final字段,或避免在可克隆類中使用final字段
  5. 線程安全問題
    • 問題:克隆過程如果不是原子的,可能導致不一致狀態
    • 解決方案:同步clone方法,或保證克隆操作的原子性

性能優化建議

為了提高原型模式的效率,可以考慮以下優化策略:

  1. 原型管理器:維護一個注冊表存儲常用原型,避免重復創建原型實例
  2. 延遲拷貝:結合享元模式,對于不變的部分共享,可變的部分延遲拷貝
  3. 并行克隆:對于大批量克隆操作,可以采用并行處理提高效率
  4. 緩存策略:緩存頻繁使用的克隆對象,減少實際克隆次數
// 原型管理器示例
public class PrototypeManager {private static Map<String, Prototype> prototypes = new HashMap<>();static {prototypes.put("sheep", new Sheep("tom", 1, "白色"));prototypes.put("monster", new Monster("dragon", 100));}public static Prototype getPrototype(String type) {return prototypes.get(type).clone();}
}

原型模式與其他設計模式的關系

與工廠方法模式比較

  1. 相似點
    • 都是創建型設計模式
    • 都可以隱藏對象創建的細節
    • 都可以提高系統靈活性
  2. 不同點
    • 工廠方法通過子類決定實例化哪個類,而原型模式通過克隆自身創建新對象
    • 工廠方法需要與產品類平行的工廠類層次,原型模式不需要
    • 原型模式可以動態獲取對象運行時狀態,工廠方法創建的是新初始化的對象

與抽象工廠模式比較

  1. 相似點
    • 都可以創建一系列相關或依賴對象
    • 都強調創建過程的封裝
  2. 不同點
    • 抽象工廠關注產品族,原型模式關注單個產品的復制
    • 抽象工廠通過不同工廠創建不同產品,原型模式通過克隆創建產品
    • 原型模式更適合創建復雜或代價高的對象

與單例模式的關系

原型模式和單例模式看似矛盾,但實際上可以結合使用:

  1. 原型單例:將單例對象作為原型,需要時可以克隆出非單例對象
  2. 單例原型管理器:使用單例模式管理原型注冊表
  3. 注意事項:實現單例的clone方法時,通常應該直接返回單例實例,而不是創建新對象
public class Singleton implements Cloneable {private static Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}@Overrideprotected Object clone() throws CloneNotSupportedException {return instance;  // 直接返回單例實例}
}

與備忘錄模式的關系

原型模式可以與備忘錄模式結合,實現對象狀態的保存和恢復:

  1. 原型作為備忘錄:使用克隆對象作為備忘錄存儲狀態
  2. 恢復狀態:通過將當前對象替換為備忘錄中的克隆對象來恢復狀態
  3. 優勢:不需要額外定義備忘錄類,實現更簡潔

實際應用案例

案例一:圖形編輯器中的圖形復制

在圖形編輯器中,用戶經常需要復制圖形元素。使用原型模式可以高效實現這一功能:

// 圖形接口
public interface Graphic extends Cloneable {void draw();Graphic clone();
}// 具體圖形實現
public class Rectangle implements Graphic {private int width;private int height;public Rectangle(int width, int height) {this.width = width;this.height = height;}@Overridepublic void draw() {System.out.println("Drawing rectangle: " + width + "x" + height);}@Overridepublic Graphic clone() {return new Rectangle(this.width, this.height);}
}// 使用示例
Graphic original = new Rectangle(100, 50);
Graphic copy = original.clone();
copy.draw();  // 輸出: Drawing rectangle: 100x50

案例二:游戲中的敵人生成

在游戲開發中,同類型敵人往往有相同的屬性和行為,但各自獨立。原型模式非常適合這種場景:

public class Enemy implements Cloneable {private String type;private int health;private int attackPower;private Position position;public Enemy(String type, int health, int attackPower) {this.type = type;this.health = health;this.attackPower = attackPower;// 初始化代價高的操作loadTextures();loadAIBehavior();}@Overridepublic Enemy clone() {try {Enemy clone = (Enemy)super.clone();// 深拷貝positionclone.position = new Position(this.position.getX(), this.position.getY());return clone;} catch (CloneNotSupportedException e) {throw new AssertionError(); // 不會發生}}public void setPosition(int x, int y) {this.position = new Position(x, y);}// 其他方法...
}// 使用示例
Enemy prototypeEnemy = new Enemy("Orc", 100, 20);
prototypeEnemy.setPosition(0, 0);// 生成多個敵人
List<Enemy> enemies = new ArrayList<>();
for(int i=0; i<10; i++) {Enemy enemy = prototypeEnemy.clone();enemy.setPosition(i*10, 0);enemies.add(enemy);
}

案例三:配置對象的復制

在系統配置管理中,我們經常需要基于某個模板配置創建多個相似配置:

public class SystemConfig implements Cloneable {private String host;private int port;private Map<String, String> settings;public SystemConfig(String host, int port) {this.host = host;this.port = port;this.settings = loadDefaultSettings(); // 耗時操作}@Overridepublic SystemConfig clone() {try {SystemConfig clone = (SystemConfig)super.clone();// 深拷貝settingsclone.settings = new HashMap<>(this.settings);return clone;} catch (CloneNotSupportedException e) {throw new AssertionError();}}// 其他方法...
}// 使用示例
SystemConfig baseConfig = new SystemConfig("localhost", 8080);// 為不同服務創建配置
SystemConfig dbConfig = baseConfig.clone();
dbConfig.setHost("db-server");
dbConfig.setPort(3306);SystemConfig cacheConfig = baseConfig.clone();
cacheConfig.setHost("cache-server");
cacheConfig.setPort(6379);

總結

原型模式是一種強大的創建型設計模式,它通過復制現有對象來創建新對象,而不是通過實例化類。這種模式特別適用于以下場景:

  1. 當創建新對象的成本較高,而復制現有對象更高效時
  2. 當系統需要獨立于其產品的創建、組合和表示時
  3. 當需要保存和恢復對象狀態時
  4. 當需要避免使用與產品層次結構平行的工廠類層次結構時

原型模式的核心在于理解深淺拷貝的區別,并根據實際需求選擇合適的拷貝策略。淺拷貝簡單高效但共享引用,深拷貝完全獨立但實現復雜。在實際開發中,通常需要權衡性能、安全性和實現復雜度來做出選擇。

Java語言內置了對原型模式的支持,通過Cloneable接口和clone()方法實現。Spring框架也廣泛應用了原型模式來管理bean的生命周期。理解原型模式的工作原理和最佳實踐,可以幫助我們設計出更靈活、更高效的面向對象系統。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/85425.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/85425.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/85425.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HuggingFace鏡像配置失效問題深度解析:Python模塊導入機制的陷阱

前言 在使用HuggingFace的transformers和datasets庫時&#xff0c;國內用戶經常會遇到網絡連接問題。雖然設置了鏡像源環境變量&#xff0c;但仍然報錯無法連接到huggingface.co。本文將深入分析這個問題的根因&#xff0c;并從Python模塊導入機制的角度解釋為什么環境變量設置…

leetcode146-LRU緩存

leetcode 146 思路 什么是LRU緩存&#xff1f; LRU&#xff08;Least Recently Used&#xff09;緩存是一種常見的緩存淘汰策略&#xff0c;核心思想是&#xff1a;當緩存容量滿時&#xff0c;優先淘汰最久未使用的數據。LeetCode 146 題要求實現一個支持get和put操作的 LR…

MQTT:構建高效物聯網通信的輕量級協議

MQTT – 輕量級物聯網消息推送協議 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是機器對機器(M2M)/物聯網(IoT)連接協議。它被設計為一個極其輕量級的發布/訂閱消息傳輸協議。對于需要較小代碼占用空間和/或網絡帶寬非常寶貴的遠程連接非常有用&#xf…

AI自動生成復雜架構圖,流程圖,思維導圖

AI自動生成復雜架構圖&#xff0c;流程圖&#xff0c;思維導圖方案 1. 背景 在我們自己去繪制架構圖&#xff0c;流程圖&#xff0c;思維導圖的時候&#xff0c;我們通常需要花費大量的時間去繪制。 目前的一些直接生圖的模型也只能生成簡單的流程圖&#xff0c;不能生成復雜…

129. 求根節點到葉節點數字之和 --- DFS +回溯(js)

129. 求根節點到葉節點數字之和 --- DFS 回溯&#xff08;js&#xff09; 題目描述解題思路完整代碼 題目描述 129. 求根節點到葉節點數字之和 解題思路 和 257. 二叉樹的所有路徑&#xff08;js&#xff09; 是一樣的思路。 不一樣的地方就是遇到葉子節點的時候把路徑拼接…

SpringBoot電腦商城項目--修改默認收貨地址

1. 修改默認收貨地址-持久層 1.1 規劃sql語句 檢測當前用戶向設置為默認收貨地址的這條數據是否存在 SELECT * FROM t_address WHERE aid#{aid} 在修改用戶的收獲默認地址之前&#xff0c;先將所有的收貨地址設置為非默認 UPDATE t_address SET is_default0 WHERE uid#{uid} …

LabVIEW FPGA 資源擴展

針對NI CompactRIO 9045 控制器 Kintex-7 70T FPGA 資源不足問題&#xff0c;通過 NI 9151 R 系列可重配置 I/O 模塊擴展外部 FPGA 處理能力&#xff0c;在保留原有機箱架構下實現實時任務分流&#xff0c;解決Slice、LUT 等資源緊張問題&#xff0c;提升系統并行處理能力。 ?…

【漏洞復現】Apache Kafka Connect 任意文件讀取漏洞(CVE-2025-27817)

文章目錄 前言一、Apache Kafka 簡介二、漏洞描述三、影響版本四、FOFA查詢語句五、漏洞原理分析六、漏洞復現七、修復建議前言 由于Apache Kafka客戶端未對用戶輸入進行嚴格驗證和限制,未經身份驗證的攻擊者可通過構造惡意配置讀取環境變量或磁盤任意內容,或向非預期位置發…

day13-軟件包管理

1.每日復盤與今日內容 1.1復盤 yum源/apt源配置文件,核心下載地址.二進制部署服務.編譯安裝軟件. 2.軟件包管理-實戰部分 2.1 yum源/apt源配置 源下載軟件的地址配置多種源 1??系統也有默認的源&#xff0c;里面也包含很多常用的軟件. 2??安裝nginx、yum源 3??安…

榕壹云快遞寄件系統:聚合快遞、智能追蹤、二次開發,一站式物流解決方案

在電商物流高速發展的今天&#xff0c;快遞寄件需求呈現爆炸式增長。傳統分散的寄件方式效率低下&#xff0c;用戶迫切需要一個整合多家快遞公司的便捷平臺。榕壹云公司開發的快遞寄件系統應運而生&#xff0c;通過聚合多家快遞資源、優化操作流程、提供豐富的功能模塊&#xf…

一款功能強大的專業CSV編輯工具

Rons Data Edit是一款為Windows操作系統設計的現代CSV文件編輯器&#xff0c;它結合了優雅、強大和易用性&#xff0c;它可以打開任何格式的分隔文本文件(如CSV、TSV等)&#xff0c;并允許用戶完全控制文件的內容和結構。 功能特點 支持明暗主題&#xff0c;可以在預定義的20多…

什么是軟件架構?和系統設計有何區別?

一、軟件架構的定義與核心要素 1.1 基本概念 軟件架構(Software Architecture)是指系統的高層結構,包含: 組件(Components)及其相互關系指導設計的架構原則和決策滿足質量屬性(Quality Attributes)的技術方案引用權威定義:IEEE 1471標準將架構描述為"系統的基本組織,…

九尾狐編程語言新算法“超維時空演算體”

一、核心架構設計 1&#xff0e;量子&#xfe63;生物混合計算基座 ◇底層采用量子糾纏拓撲網絡&#xff0c;處理超越經 典計算復雜度的問題&#xff08;如 NP - Hard 優化&#xff09;&#xff0e;中層嵌入類腦脈沖神經網絡&#xff0c;模擬人腦跨領域聯想能力&#xff0c;…

RoboVerse--為機器人學習打造的大一統世界--UC Berkeley...--2025.4.26

ROBOVERSE 包含一個可擴展的仿真平臺、大規模的合成數據集&#xff0c;以及統一的基準測試。 該仿真平臺通過統一協議&#xff0c;支持新任務和演示的無縫接入&#xff0c;保證了靈活性和可擴展性。該數據集包含 1,000 多個多樣化任務及超過 1,000 萬個狀態轉換&#xff0c;構…

Fiddler抓包工具實戰指南:結合Charles、Postman優化Web與移動調試流程

在Web開發與移動端調試的工作流程中&#xff0c;網絡請求的可視化、分析和控制能力對開發效率有著決定性影響。特別是在處理復雜接口聯調、性能瓶頸排查&#xff0c;甚至安全漏洞分析時&#xff0c;一款可靠的抓包工具幾乎成為了每一位開發者的“標配”。 Fiddler作為長期深受…

6/19作業

思維導圖 單選題 樹 1. 向一棵平衡二叉樹中插入一個結點后&#xff0c;一定會改變其平衡性。 &#xff08; &#xff09; A 正確 B 錯誤 正確答案&#xff1a;B 你的答案&#xff1a;A 官方解析&#xff1a; 向平衡二叉樹中插入節點并不一定會改變其平衡性。平衡二叉樹(如AVL樹…

angular 圖斑點擊,列表選中并滾動到中間位置

如圖所示&#xff1a; html代碼&#xff1a; 1. #listContainer 2. [attr.data-id]"center.id" <div class"resTableCss" #listContainer><div *ngFor"let center of tbList" [attr.data-id]"center.id" class"res-it…

Java線程同步的簡單理解

為什么需要線程同步 對于以下代碼&#xff1a;兩個線程對同一個變量分別進行100000次加一和減一操作&#xff0c;但是每次運行的輸出基本都是不同的&#xff08;注意線程的join操作保證了兩個線程都運行完之后才執行System.out.println&#xff09; import org.junit.Test;pu…

Makefile的通用模板 + 倒計時小程序(13)

文章目錄 Makefile 的通用模板1. Makefile 的推導原則2. 設計 Makefile 的通用模板3. 通用模板代碼&#xff08;可以直接拿來用&#xff09; Linux 第一個系統程序-進度條&#xff08;7-3.00.00&#xff09;1. 補充回車與換行2. 行緩沖區3. 倒計時小程序 Makefile 的通用模板 …

【ArcGIS】水文分析與流域劃分

【ArcGIS】水文分析與流域劃分 一、基礎數據處理1、下載數據2、拼接DEM數據3、填充洼地4、流向分析5、流量分析6、河網生成&#xff08;柵格計算器&#xff09;7、河網分級8、河流鏈接&#xff08;提取子流域的關鍵&#xff09; 二、多個小流域提取1、捕捉傾瀉點2、集水區&…