【設計模式】【創建型模式】原型模式(Prototype)

👋hi,我不是一名外包公司的員工,也不會偷吃茶水間的零食,我的夢想是能寫高端CRUD
🔥 2025本人正在沉淀中… 博客更新速度++
👍 歡迎點贊、收藏、關注,跟上我的更新節奏
🎵 當你的天空突然下了大雨,那是我在為你炸烏云

文章目錄

  • 一、入門
    • 什么是原型模式?
    • 為什么要有原型模式?
    • 如何實現原型模式?
  • 二、原型模式在框架源碼中的使用
    • JDK 的 Object.clone()
    • Java 集合框架中的 ArrayList.clone()
    • Spring Framework 中的 Prototype Bean
  • 三、總結
    • 原型模式的優點
    • 原型模式的缺點
    • 原型模式的適用場景

一、入門

什么是原型模式?

原型模式(Prototype Pattern)是一種創建型設計模式,它通過復制現有對象來創建新對象,而不是通過實例化類。
原型模式的核心是克隆(Clone),即通過復制現有對象來創建新對象。Java 提供了 Cloneable 接口和 clone() 方法來實現對象的淺拷貝。

為什么要有原型模式?

  1. 對象創建成本高
    • 問題:某些對象的創建過程可能非常復雜,涉及大量的計算或資源消耗。例如,數據庫連接、網絡請求、復雜的初始化過程等。
    • 解決方案:通過原型模式,可以直接復制現有對象,避免重復進行高成本的初始化過程。
  2. 需要動態配置對象
    • 問題:在某些情況下,對象的配置需要在運行時動態確定,而不是在編譯時確定。如果每次都需要重新創建和配置對象,會導致代碼復雜且難以維護。
    • 解決方案:原型模式允許通過復制現有對象來創建新對象,并根據需要動態修改其配置。
  3. 避免子類化
    • 問題:在某些情況下,通過繼承來擴展對象的功能會導致類層次結構復雜,難以維護。
    • 解決方案:原型模式通過復制現有對象來創建新對象,而不是通過繼承來擴展功能,從而簡化了類層次結構。
  4. 保持對象狀態
    • 問題:在某些情況下,需要創建與現有對象狀態相同的新對象。如果每次都手動復制對象的狀態,會導致代碼冗余且容易出錯。
    • 解決方案:原型模式通過克隆現有對象來自動復制其狀態,減少了手動復制狀態的工作量。

如何實現原型模式?

原型模式由以下角色組成:

  1. 原型接口(Prototype Interface)
    • 定義克隆方法的接口或抽象類。
    • 在 Java 中,通常使用 Cloneable 接口來標記類支持克隆。
  2. 具體原型類(Concrete Prototype)
    • 實現原型接口的具體類,負責實現克隆方法。
    • 通常需要重寫 clone() 方法來定義具體的克隆邏輯。
  3. 客戶端(Client)
    • 使用原型對象的類,通過調用原型對象的克隆方法來創建新對象。

【案例】打印身份證
在這里插入圖片描述
假設你需要復印身份證,每次復印時,原始身份證的內容(姓名、身份證號、地址等)是固定的,但復印件的用途可能不同(如用于銀行開戶、辦理簽證等)。如果每次都重新填寫身份證信息,效率很低。
原型模式解決方案:

  1. 身份證原件(原型):包含固定的個人信息。
  2. 復印件(克隆對象):復制原件的內容,并根據用途添加額外信息(如用途備注)。

原型接口(Cloneable 是 Java 內置接口): Prototype接口

interface Prototype extends Cloneable {Prototype clone();
}

具體原型類(Concrete Prototype) IDCard

class IDCard implements Prototype {private String name;private String idNumber;private String address;private String purpose; // 復印件的用途public IDCard(String name, String idNumber, String address) {this.name = name;this.idNumber = idNumber;this.address = address;}public void setPurpose(String purpose) {this.purpose = purpose;}@Overridepublic IDCard clone() {try {return (IDCard) super.clone(); // 調用 Object 的 clone() 方法} catch (CloneNotSupportedException e) {throw new RuntimeException(e);}}@Overridepublic String toString() {return "IDCard{" +"name='" + name + '\'' +", idNumber='" + idNumber + '\'' +", address='" + address + '\'' +", purpose='" + purpose + '\'' +'}';}
}

客戶端

class CopyMachine {public static void main(String[] args) {// 創建身份證原件IDCard originalIDCard = new IDCard("張三", "123456789012345678", "北京市朝陽區");// 復印身份證用于銀行開戶IDCard copyForBank = originalIDCard.clone();copyForBank.setPurpose("銀行開戶");// 復印身份證用于辦理簽證IDCard copyForVisa = originalIDCard.clone();copyForVisa.setPurpose("辦理簽證");// 打印結果System.out.println("原件: " + originalIDCard);System.out.println("銀行開戶復印件: " + copyForBank);System.out.println("辦理簽證復印件: " + copyForVisa);}
}

二、原型模式在框架源碼中的使用

JDK 的 Object.clone()

Java 的根類 Object 提供了 clone() 方法,它是原型模式的底層實現基礎。任何實現 Cloneable 接口的類都可以通過 clone() 方法創建新對象。

public class Object {protected native Object clone() throws CloneNotSupportedException;
}

使用約束

  • 必須實現 Cloneable 接口:否則調用 clone() 會拋出 CloneNotSupportedException
  • 默認是淺拷貝:需要深拷貝時,必須手動重寫 clone() 方法。

Java 集合框架中的 ArrayList.clone()

Java 的 ArrayList 類實現了 Cloneable 接口,其 clone() 方法通過淺拷貝快速復制一個新的列表。

ArrayList<String> original = new ArrayList<>();
original.add("A");
original.add("B");ArrayList<String> copy = (ArrayList<String>) original.clone();
copy.add("C");System.out.println(original); // 輸出 [A, B]
System.out.println(copy);     // 輸出 [A, B, C]
源碼實現
public class ArrayList<E> implements Cloneable {// ...public Object clone() {try {ArrayList<?> v = (ArrayList<?>) super.clone();v.elementData = Arrays.copyOf(elementData, size);v.modCount = 0;return v;} catch (CloneNotSupportedException e) {throw new InternalError(e);}}
}

Spring Framework 中的 Prototype Bean

Spring 框架中的 Bean 作用域(Scope)之一是 prototype,它表示每次從容器中獲取 Bean 時都會創建一個新的實例。這本質上是原型模式的一種應用。

<!-- XML 配置 -->
<bean id="prototypeBean" class="com.example.PrototypeBean" scope="prototype"/>
// Java 代碼中獲取 Bean
ApplicationContext context = ...;
PrototypeBean bean1 = context.getBean(PrototypeBean.class);
PrototypeBean bean2 = context.getBean(PrototypeBean.class);// bean1 和 bean2 是兩個不同的實例
System.out.println(bean1 == bean2); // 輸出 false

設計思想

  • 核心機制:Spring 容器內部維護一個原型 Bean 的模板,每次調用 getBean() 時,基于模板創建一個新對象(通過反射或 CGLIB 動態代理)。
  • 優勢:避免單例 Bean 的線程安全問題,適用于需要獨立狀態的場景(如 HTTP 請求處理)。

三、總結

原型模式的優點

  1. 高效創建對象
    • 通過復制現有對象來創建新對象,避免了重復的初始化過程,特別適用于創建成本較高的對象(如數據庫連接、復雜計算對象)。
    • 例如,Spring 的 Prototype Bean 每次請求都會創建一個新實例,避免了單例 Bean 的線程安全問題。
  2. 動態配置對象
    • 可以在運行時動態修改克隆對象的屬性,而不需要重新初始化。
    • 例如,復制一個配置對象后,可以根據需要調整某些參數。
  3. 減少子類化
    • 通過復制現有對象來創建新對象,而不是通過繼承來擴展功能,避免了類層次結構的復雜性。
    • 例如,JavaScript 中的原型繼承就是通過復制原型對象來實現的。
  4. 標準化對象創建
    • 提供統一的克隆接口(如 Cloneable),使得對象創建過程更加標準化和可控。

原型模式的缺點

  1. 深拷貝與淺拷貝問題
    • 默認的 clone() 方法是淺拷貝,如果對象包含引用類型字段,克隆對象和原對象會共享這些字段,可能導致意外的副作用。
    • 實現深拷貝需要額外的工作(如手動復制引用類型字段或使用序列化工具)。
  2. 實現復雜度
    • 如果對象結構非常復雜(如包含嵌套對象、循環引用等),實現深拷貝可能會變得復雜且容易出錯。
  3. 破壞封裝性
    • clone() 方法是 Object 類的受保護方法,需要在子類中重寫并公開,這可能破壞類的封裝性。
  4. 性能問題
    • 深拷貝(如基于序列化的拷貝)可能比較耗時,特別是在對象結構復雜或數據量大的情況下。

原型模式的適用場景

  1. 對象創建成本高
    • 當對象的創建過程涉及復雜的計算、資源消耗(如數據庫連接、網絡請求)或耗時操作時,使用原型模式可以顯著提高性能。
    • 例如,Spring 的 Prototype Bean 適用于需要獨立狀態的場景。
  2. 需要動態配置對象
    • 當對象的配置需要在運行時動態確定時,可以通過克隆現有對象并修改其屬性來實現。
    • 例如,復制一個配置模板并根據環境調整參數。
  3. 避免子類化
    • 當需要通過擴展對象的功能來創建新對象,但又不想引入復雜的類層次結構時,可以使用原型模式。
    • 例如,JavaScript 中的原型繼承。
  4. 需要保持對象狀態一致性
    • 當需要創建與現有對象狀態相同的新對象時,可以通過克隆來確保狀態一致性。
    • 例如,游戲中的敵人生成、緩存對象的復制。
  5. 框架中的對象管理
    • 在框架中,原型模式常用于管理對象的生命周期和創建過程(如 Spring 的 Prototype Bean、Java 集合框架的 clone() 方法)。

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

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

相關文章

Weblogic 反序列化漏洞深度剖析與復現

目錄 一、引言 二、Weblogic 反序列化漏洞原理 &#xff08;一&#xff09;什么是反序列化 &#xff08;二&#xff09;Weblogic 反序列化漏洞產生機制 三、Weblogic 反序列化漏洞危害 四、Weblogic 反序列化漏洞復現 &#xff08;一&#xff09;復現環境準備 &#xff…

2025年02月19日Github流行趨勢

項目名稱&#xff1a;OmniParser 項目地址url&#xff1a;https://github.com/microsoft/OmniParser 項目語言&#xff1a;Jupyter Notebook 歷史star數&#xff1a;12878 今日star數&#xff1a;2153 項目維護者&#xff1a;yadong-lu, ThomasDh-C, aliencaocao, nmstoker, kr…

深入解析 iOS 視頻錄制(三):完整錄制流程的實現與整合

深入解析 iOS 視頻錄制&#xff08;一&#xff09;&#xff1a;錄制管理核心MWRecordingController 類的設計與實現 深入解析iOS視頻錄制&#xff08;二&#xff09;&#xff1a;自定義UI的實現??????? 深入解析 iOS 視頻錄制&#xff08;三&#xff09;&#xff1a;完…

基于豆瓣2025電影數據可視化分析系統的設計與實現

??本項目旨在通過對豆瓣電影數據進行綜合分析與可視化展示&#xff0c;構建一個基于Python的大數據可視化系統。通過數據爬取收集、清洗、分析豆瓣電影數據&#xff0c;我們提供了一個全面的電影信息平臺&#xff0c;為用戶提供深入了解電影產業趨勢、影片評價與演員表現的工…

tcp協議連接,和傳輸數據

1、連接 這個是通用的 2、傳送數據 當連接建立后&#xff0c;客戶端和服務器都可以主動發送數據&#xff0c;分別如下 1》客戶端先發送數據 這里是單向的&#xff0c;服務器沒有對客戶端的數據內容進行應答&#xff0c;只是單純的對報文應答ack 2》服務器先發送數據

2024年國賽高教杯數學建模C題農作物的種植策略解題全過程文檔及程序

2024年國賽高教杯數學建模 C題 農作物的種植策略 原題再現 根據鄉村的實際情況&#xff0c;充分利用有限的耕地資源&#xff0c;因地制宜&#xff0c;發展有機種植產業&#xff0c;對鄉村經濟的可持續發展具有重要的現實意義。選擇適宜的農作物&#xff0c;優化種植策略&…

鴻蒙開發:V2版本裝飾器之@Monitor裝飾器

前言 本文代碼案例基于Api13。 隨著官方的迭代&#xff0c;在新的Api中&#xff0c;對于新的應用開發&#xff0c;官方已經建議直接使用V2所屬的裝飾器進行開發了&#xff0c;所以&#xff0c;能上手V2的盡量上手V2吧&#xff0c;畢竟&#xff0c;V2是V1的增強版本&#xff0c;…

國產編輯器EverEdit - 獨門暗器:自動監視剪貼板內容

1 監視剪貼板 1.1 應用場景 如果需要對剪貼板的所有歷史進行記錄&#xff0c;并進行分析和回顧&#xff0c;則可以使用監視剪貼板功能&#xff0c;不僅在EverEdit中的復制會記錄&#xff0c;在其他應用的復制也會記錄。 1.2 使用方法 新建一個空文檔(重要&#xff1a;防止擾亂…

pdf轉換成word在線 簡單好用 支持批量轉換 效率高 100%還原

pdf轉換成word在線 簡單好用 支持批量轉換 效率高 100%還原 在數字化辦公的浪潮中&#xff0c;文檔格式轉換常常讓人頭疼不已&#xff0c;尤其是 PDF 轉 Word 的需求極為常見。PDF 格式雖然方便閱讀和傳輸&#xff0c;但難以編輯&#xff0c;而 Word 格式卻能靈活地進行內容修…

深入探索C語言中的字符串處理函數:strstr與strtok

在C語言的字符串處理領域&#xff0c; strstr 和 strtok 是兩個非常重要的函數&#xff0c;它們各自承擔著獨特的功能&#xff0c;為開發者處理字符串提供了強大的支持。 一、strstr函數&#xff1a;字符串查找的利器 strstr 函數用于在一個字符串中查找另一個字符串的首次出現…

AIGC(生成式AI)試用 21 -- Python調用deepseek API

1. 安裝openai pip3 install openai########################## Collecting openaiUsing cached openai-1.61.1-py3-none-any.whl.metadata (27 kB) Collecting anyio<5,>3.5.0 (from openai)Using cached anyio-4.8.0-py3-none-any.whl.metadata (4.6 kB) Collecting d…

關于使用雪花算法生成唯一ID,返回給前端ID不一致的問題

問題 在某個項目中,使用雪花算法生成的唯一ID,從數據庫查詢到數據后返回給前端,但是前端接受到的數據ID和數據庫原先生成的不一致 但是前端展示的數據: 原因 原因是后端使用Long類型來存儲雪花算法生成的ID,但是這個數值已經超過前端數值類型的范圍,導致前端在存儲這個數值…

Windows 啟動 SSH 服務

Windows 啟動 SSH 服務 一、OpenSSH Server 安裝 以 Win10 系統為例 打開設置 -> 系統 -> 可選功能 在 添加的功能 查看是否安裝了 OpenSSH 服務 或者 OpenSSH Server 如果沒有安裝&#xff0c;找到 系統->添加可選功能 -> 查看功能->搜索 OpenSSH 服務 ->…

C#功能測試

List 內部元素為引用 src[0]為"11" List<Source> src new List<Source>(); src.Add(new Source() { Name "1", Age 1, Description "1" }); src.Add(new Source() { Name "2", Age 2, Description "2"…

大數據SQL調優專題——Flink執行原理

引入 上一篇我們了解了Spark&#xff0c;相比起MapReduce來說&#xff0c;它確實已經快了超級多了&#xff0c;但是人類的欲望是沒有止境的&#xff0c;這也是推動人類進步的動力。 Flink就是為了滿足實時響應的場景需求誕生的。 其實在Flink之前&#xff0c;實時處理其實已…

計算機視覺:神經網絡實戰之手勢識別(附代碼)

第一章&#xff1a;計算機視覺中圖像的基礎認知 第二章&#xff1a;計算機視覺&#xff1a;卷積神經網絡(CNN)基本概念(一) 第三章&#xff1a;計算機視覺&#xff1a;卷積神經網絡(CNN)基本概念(二) 第四章&#xff1a;搭建一個經典的LeNet5神經網絡(附代碼) 第五章&#xff1…

win11安裝wsl報錯:無法解析服務器的名稱或地址(啟用wsl2)

1. 啟用wsl報錯如下 # 查看可安裝的 wsl --install wsl --list --online此原因是因為沒有開啟DNS的原因&#xff0c;所以需要我們手動開啟DNS。 2. 按照如下配置即可 Google的DNS&#xff08;8.8.8.8和8.8.4.4) 全國通用DNS地址 (114.114.114.114) 3. 運行以下命令來重啟 WSL…

開源模型應用落地-DeepSeek-R1-Distill-Qwen-7B-LoRA微調-LLaMA-Factory-單機單卡-V100(一)

一、前言 如今&#xff0c;大語言模型領域熱鬧非凡&#xff0c;各種模型不斷涌現。DeepSeek-R1-Distill-Qwen-7B 模型憑借其出色的效果和性能&#xff0c;吸引了眾多開發者的目光。而 LLaMa-Factory 作為強大的微調工具&#xff0c;能讓模型更好地滿足個性化需求。 在本篇中&am…

k8s-對接NFS存儲

一、前提條件 1、NFS_Server 部署好了。 2、網絡可達。 二、 使用方式 1、CSI **項目地址 https://github.com/kubernetes-csi/csi-driver-nfs#readme Install NFS CSI driver v4.10.0 version on a kubernetes cluster If you have already installed Helm, you can a…

【動態路由】系統Web URL資源整合系列(后端技術實現)【nodejs實現】

需求說明 軟件功能需求&#xff1a;反向代理功能&#xff08;描述&#xff1a;apollo、eureka控、apisix、sentinel、普米、kibana、timetask、grafana、hbase、skywalking-ui、pinpoint、cmak界面、kafka-map、nacos、gateway、elasticsearch、 oa-portal 業務應用等多個web資…