設計模式(五)創建型:原型模式詳解

設計模式(五)創建型:原型模式詳解

原型模式(Prototype Pattern)是 GoF 23 種設計模式中的創建型模式之一,其核心價值在于通過復制現有對象來創建新對象,而不是通過 new 關鍵字調用構造函數。它特別適用于對象創建成本高、構造復雜或運行時動態決定類型擴展的場景。原型模式通過克隆機制規避了昂貴的初始化過程,提升了性能,并支持在不依賴具體類的情況下動態生成對象,是實現對象復用與運行時靈活性的重要手段。在配置管理、游戲開發、文檔模板系統、對象池等場景中具有廣泛應用。

一、原型模式詳細介紹

原型模式解決的是“對象創建效率”與“運行時靈活性”的問題。當一個對象的創建過程涉及復雜的數據加載、資源分配或計算邏輯時,頻繁使用構造函數會導致性能瓶頸。原型模式通過“克隆”一個已存在的實例(即“原型”)來快速生成新對象,避免重復執行初始化邏輯。

該模式涉及以下核心角色:

  • Prototype(原型接口):聲明一個克隆(clone)方法,用于返回當前對象的副本。通常在 Java 中通過實現 Cloneable 接口并重寫 Object.clone() 方法實現。
  • ConcretePrototype(具體原型類):實現 Prototype 接口,提供具體的克隆邏輯。它定義了如何復制自身的狀態。
  • Client(客戶端):持有對 Prototype 的引用,通過調用 clone() 方法而非構造函數來創建新對象。

原型模式的關鍵在于克隆的深度

  • 淺克隆(Shallow Clone):僅復制對象本身及其基本類型字段,對于引用類型字段,只復制引用地址,不復制被引用的對象。Java 默認的 Object.clone() 實現即為淺克隆。
  • 深克隆(Deep Clone):不僅復制對象本身,還遞歸復制其所有引用對象,確保新對象與原對象完全獨立,互不影響。

選擇淺克隆還是深克隆取決于業務需求:若對象包含共享狀態或大型資源(如緩存、連接池),淺克隆可節省內存;若要求對象完全獨立,則需深克隆。

與“工廠模式”相比,原型模式不依賴類的構造邏輯,而是基于現有實例進行復制,因此更適合運行時動態配置對象的場景。例如,系統啟動時加載一個“默認配置”對象作為原型,后續所有新配置均基于此原型克隆并修改,避免重復解析配置文件。

二、原型模式的UML表示

以下是原型模式的標準 UML 類圖:

implements
implements
contains
?interface?
Prototype
+clone()
ConcretePrototypeA
-field1: String
-field2: int
-reference: Component
+clone()
ConcretePrototypeB
-data: List<String>
+clone()
Component
-name: String

圖解說明

  • Prototype 接口定義 clone() 方法,返回一個 Prototype 類型的對象。
  • ConcretePrototypeAConcretePrototypeB 是具體實現類,各自實現 clone() 方法。
  • ConcretePrototypeA 包含一個 Component 類型的引用字段,克隆時需決定是淺復制還是深復制該引用。
  • 客戶端通過調用 prototype.clone() 獲取新對象,無需知道其具體類名,實現了創建過程的解耦。

三、一個簡單的Java程序實例

以下是一個基于原型模式的 Java 示例,模擬配置對象的克隆過程:

import java.util.ArrayList;
import java.util.List;// 組件類:被引用的對象
class ServerConfig {private String host;private int port;public ServerConfig(String host, int port) {this.host = host;this.port = port;}// 提供復制構造函數用于深克隆public ServerConfig copy() {return new ServerConfig(this.host, this.port);}// Getter and Setterpublic String getHost() { return host; }public void setHost(String host) { this.host = host; }public int getPort() { return port; }public void setPort(int port) { this.port = port; }@Overridepublic String toString() {return "ServerConfig{" +"host='" + host + '\'' +", port=" + port +'}';}
}// 抽象原型接口
interface Configuration extends Cloneable {Configuration clone();
}// 具體原型類:應用配置
class AppConfiguration implements Configuration {private String appName;private int timeout;private boolean debugMode;private ServerConfig primaryServer;           // 引用類型private List<String> allowedOrigins;          // 集合類型// 構造函數:用于創建初始原型public AppConfiguration(String appName, int timeout, boolean debugMode,ServerConfig primaryServer, List<String> allowedOrigins) {this.appName = appName;this.timeout = timeout;this.debugMode = debugMode;this.primaryServer = primaryServer;this.allowedOrigins = new ArrayList<>(allowedOrigins); // 防止外部修改}// 深克隆實現@Overridepublic Configuration clone() {try {// 先調用 Object.clone() 進行淺克隆AppConfiguration cloned = (AppConfiguration) super.clone();// 對引用類型字段進行深克隆cloned.primaryServer = this.primaryServer.copy(); // 使用復制構造函數cloned.allowedOrigins = new ArrayList<>(this.allowedOrigins); // 復制集合內容return cloned;} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone failed", e);}}// Getter and Setter 方法(省略部分)public String getAppName() { return appName; }public void setAppName(String appName) { this.appName = appName; }public int getTimeout() { return timeout; }public void setTimeout(int timeout) { this.timeout = timeout; }public boolean isDebugMode() { return debugMode; }public void setDebugMode(boolean debugMode) { this.debugMode = debugMode; }public ServerConfig getPrimaryServer() { return primaryServer; }public void setPrimaryServer(ServerConfig primaryServer) { this.primaryServer = primaryServer; }public List<String> getAllowedOrigins() { return new ArrayList<>(allowedOrigins); }@Overridepublic String toString() {return "AppConfiguration{" +"appName='" + appName + '\'' +", timeout=" + timeout +", debugMode=" + debugMode +", primaryServer=" + primaryServer +", allowedOrigins=" + allowedOrigins +'}';}
}// 客戶端使用示例
public class PrototypePatternDemo {public static void main(String[] args) {// 創建一個“默認配置”原型對象ServerConfig defaultServer = new ServerConfig("localhost", 8080);List<String> defaultOrigins = List.of("https://example.com", "https://api.example.com");AppConfiguration defaultConfig = new AppConfiguration("MyApp",30,false,defaultServer,defaultOrigins);System.out.println("=== 原始原型 ===");System.out.println(defaultConfig);// 克隆原型并修改部分配置,用于開發環境AppConfiguration devConfig = (AppConfiguration) defaultConfig.clone();devConfig.setAppName("MyApp-Dev");devConfig.setTimeout(60);devConfig.setDebugMode(true);devConfig.getPrimaryServer().setHost("dev-server.local");devConfig.getAllowedOrigins().add("http://localhost:3000");System.out.println("\n=== 開發環境配置(克隆后修改)===");System.out.println(devConfig);// 驗證原始對象未被影響(深克隆效果)System.out.println("\n=== 原始原型是否被修改?===");System.out.println(defaultConfig);// 輸出顯示 defaultConfig 的 primaryServer 仍為 localhost,allowedOrigins 無 localhost:3000}
}

運行說明

  • defaultConfig 作為原型對象,可能通過復雜過程(如讀取配置文件、數據庫查詢)創建。
  • devConfig 通過 clone() 方法創建,避免重復初始化。
  • clone() 中實現了深克隆,確保 devConfig 修改 primaryServerallowedOrigins 不影響 defaultConfig
  • 客戶端無需知道 AppConfiguration 的構造細節,只需調用 clone() 即可獲得新實例。

四、總結

原型模式通過對象克隆機制,實現了以下關鍵優勢:

  • 提升性能:避免重復執行昂貴的初始化邏輯,尤其適合大型或復雜對象。
  • 簡化對象創建:無需了解構造參數,只需復制已有實例。
  • 支持運行時動態性:可在運行時基于用戶配置或環境動態生成對象。
  • 實現對象解耦:客戶端不依賴具體類,僅通過接口調用 clone()

但也存在缺點:

  • 克隆邏輯復雜:深克隆需手動處理所有引用字段,易出錯。
  • 內存開銷:每個克隆對象都占用獨立內存,淺克隆可能引發意外共享。
  • 不適用于所有場景:若對象狀態頻繁變化或包含臨時資源(如連接),克隆可能導致不一致。

因此,應在“創建成本”與“內存/維護成本”之間權衡使用。

架構師洞見:
原型模式是“對象復用”與“運行時靈活性”的典范。在現代架構中,其思想已融入配置中心(如 Spring Cloud Config)、對象池(如數據庫連接池預熱)、游戲實體生成、A/B 測試配置分發等場景。架構師應認識到:原型模式的本質是將“對象模板”與“實例化過程”分離,實現“一次構建,多次復用”。未來,隨著云原生和 Serverless 架構的發展,函數冷啟動問題使得“預初始化實例池 + 克隆分發”成為優化啟動延遲的有效策略。此外,結合序列化(JSON/XML/Binary)實現跨進程或跨服務的原型傳遞,將進一步拓展其應用邊界。掌握原型模式,有助于設計出高性能、低延遲、高彈性的系統,是應對高并發與動態配置挑戰的重要工具。

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

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

相關文章

K8S 八 數據存儲-高級存儲PV PVC 生命周期;配置存儲ConfigMap Secret

目錄數據存儲 Volume8.1 基本存儲8.1.1 EmptyDir8.1.2 HostPath 掛載目錄8.1.3 NFSnfs的服務8.2 高級存儲8.2.1 PV和PVC8.2.2 PV 持久化卷申請8.2.3 PVC 資源申請PVC的配置參數8.2.4 生命周期配置存儲8.3.1 ConfigMap8.3.2 Secret數據存儲 Volume Kubernetes的Volume支持多種類…

Baumer工業相機堡盟工業相機如何通過YoloV8深度學習模型實現輪船檢測識別(C#代碼UI界面版)

Baumer工業相機堡盟工業相機如何通過YoloV8深度學習模型實現輪船檢測識別&#xff08;C#代碼UI界面版&#xff09;工業相機使用YoloV8模型實現輪船檢測識別工業相機通過YoloV8模型實現輪船檢測識別的技術背景在相機SDK中獲取圖像轉換圖像的代碼分析工業相機圖像轉換Bitmap圖像格…

自習室預約小程序的設計與實現

自習室預約小程序的設計與實現現代學習環境對高效、便捷的預約系統需求日益增長。自習室預約小程序結合前沿技術棧&#xff0c;提供流暢的用戶體驗和強大的后臺管理功能&#xff0c;滿足學生、職場人士等群體的自習需求。技術架構與核心功能Vue.js 構建動態前端界面 采用 Vue.j…

Docker 實戰大綱

文章目錄Docker 實戰 – Mysql &#xff08;敬請期待……&#xff09;

從一個“詭異“的C++程序理解狀態機、防抖與系統交互

引言 在編程世界中&#xff0c;有時一個看似簡單的代碼片段可能隱藏著令人驚訝的復雜性。本文將從一個"故意設計"的C程序出發&#xff0c;深入探討其背后涉及的狀態機模式、防抖機制以及操作系統與控制臺的交互原理。通過這個案例&#xff0c;我們不僅能理解這些核心…

NAS-Bench-101: Towards Reproducible Neural Architecture Search

概述這篇題為"NAS-Bench-101: Towards Reproducible Neural Architecture Search"的論文由Chris Ying等人合作完成&#xff0c;旨在解決神經網絡架構搜索(NAS)領域面臨的重大挑戰&#xff1a;計算資源需求高和實驗難以復現的問題。論文提出了NAS-Bench-101&#xff0…

SpringBoot整合Fastexcel/EasyExcel導出Excel導出多個圖片

整個工具的代碼都在Gitee或者Github地址內 gitee&#xff1a;solomon-parent: 這個項目主要是總結了工作上遇到的問題以及學習一些框架用于整合例如:rabbitMq、reids、Mqtt、S3協議的文件服務器、mongodb、xxl-job、powerjob還有用Docker compose部署各類中間組件。如果大家有…

網絡原理--HTTPHTTPS

目錄 一、HTTP 1.1 HTTP是什么 1.2 HTTP協議的工作過程 1.3 HTTP協議格式 1.3.1 抓包工具的使用 1.3.2 抓包結果 1.4 HTTP請求 1.4.1 URL 1.4.2 認識“方法” (method) 1.4.3 認識請求“報頭”(header) 1.4.4 認識請求“正文”(body) 1.5 HTTP 響應詳解 1.5.1 HTTP…

『 C++ 入門到放棄 』- 哈希表

一、哈希的概念 哈希&#xff0c;也稱「 散列 」是一種用來進行高效查找的數據結構&#xff0c;查找的時間復雜度平均為O(1)&#xff0c;其本質就是依賴哈希函數這個算法來將 key 和該 key 存儲位置建立一個映射關系。 而因為是有著映射關系&#xff0c;所以哈希的事件復雜度為…

零售收銀系統開源代碼全解析:連鎖門店一體化解決方案(含POS+進銷存+商城)

過去10年&#xff0c;收銀系統技術經歷了從單機版到云服務、從單純結算到全渠道整合的快速演進。面對連鎖多門店、AI稱重、智能分賬、跨店庫存同步等新需求&#xff0c;很多企業的現有傳統saas系統已顯乏力。本文將梳理收銀系統關鍵技術指標&#xff0c;助您在系統升級時做出明…

能源高效利用如何實現?樓宇自控系統智能化監管建筑設備

隨著全球能源危機日益嚴峻和“雙碳”目標的持續推進&#xff0c;建筑領域作為能耗大戶&#xff08;約占社會總能耗的40%&#xff09;&#xff0c;其節能潛力備受關注。樓宇自控系統&#xff08;Building Automation System&#xff0c;簡稱BAS&#xff09;作為建筑智能化的核心…

校園二手交易小程序的設計與實現

文章目錄前言詳細視頻演示具體實現截圖后端框架SpringBoot微信小程序持久層框架MyBaits成功系統案例&#xff1a;參考代碼數據庫源碼獲取前言 博主介紹:CSDN特邀作者、985高校計算機專業畢業、現任某互聯網大廠高級全棧開發工程師、Gitee/掘金/華為云/阿里云/GitHub等平臺持續…

Redis(二):Redis高級特性和應用(慢查詢、Pipeline、事務)

Redis的慢查詢 許多存儲系統&#xff08;例如 MySQL)提供慢查詢日志幫助開發和運維人員定位系統存在的慢操作。所謂慢查詢日志就是系統在命令執行前后計算每條命令的執行時間&#xff0c;當超過預設閥值,就將這條命令的相關信息&#xff08;例如:發生時間&#xff0c;耗時&…

如何為你的WordPress網站選擇合適的安全插件

在管理WordPress網站時&#xff0c;安全因素至關重要。由于WordPress的廣泛使用&#xff0c;它也成為了黑客攻擊的首要目標。為了避免潛在的安全風險&#xff0c;選擇合適的安全插件至關重要。而Wordfence和iThemes&#xff0c;作為兩款頗具人氣的WordPress安全插件&#xff0c…

我們使用Rust開發的AI知識庫應用

這段時間陸陸續續的開發了2個AI知識庫應用&#xff0c;一個面向企業&#xff0c;一個面向C端用戶。 飛樹智庫&#xff1a;一個安全高效的面向 企業的知識庫平臺&#xff08;https://fskb.coderbox.cn/&#xff09;。 小飛樹&#xff1a;一個專注于個人知識管理的AI應用&#…

自動化測試實戰篇

目錄 1. 自動化實施步驟 1.1 編寫web測試用例 1.2 自動化測試腳本開發 1.3 將自動化測試補充至測試報告 1. 自動化實施步驟 1.1 編寫web測試用例 1.2 自動化測試腳本開發 TestDevelopment: 測試用例 - Gitee.comhttps://gitee.com/Axurea/test-development/tree/master/2…

idea 服務器Debug端口啟動設置

一&#xff1a;在阿里云服務器安全組已經設置了端口授權對象&#xff1a;正確命令&#xff1a;nohup java -Xdebug -Xrunjdwp:transportdt_socket,servery,suspendn,address9998 -jar -Duser.timezoneGMT08 -Xms256m -Xmx256m /opt/projects/*/*/*-starter-1.0-SNAPSHOT.jar -…

大模型量化004

Bert P-tuning BertPET、BertP-Tuning Chain of Thought Few shot Cot Auto-COT 解決手動編寫高質量CoT示例麻煩耗時的問題 Auto COT 自動思維鏈生成器 1.業務場景&#xff1a; 每天收到很多反饋&#xff0c;之前需要人工整理&#xff0c;找到重點&#xff0c;做判斷那些需要立…

C#(基本語法)

數據類型C#是一種強類型語言&#xff0c;變量必須聲明類型。基本數據類型包括整型&#xff08;int、long&#xff09;、浮點型&#xff08;float、double&#xff09;、布爾型&#xff08;bool&#xff09;、字符型&#xff08;char&#xff09;和字符串型&#xff08;string&a…

ARM-I2C軟實現

開發流程引腳初始化引腳功能定義實現讀操作實現寫操作GD32F4軟件I2C初始化void SoftI2C_init() {// 時鐘配置rcu_periph_clock_enable(SCL_RCU);// 設置輸出模式gpio_mode_set(SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SCL_PIN);gpio_output_options_set(SCL_PORT, GPIO_O…