設計模式精講 Day 5:原型模式(Prototype Pattern)

【設計模式精講 Day 5】原型模式(Prototype Pattern)


文章內容

在“設計模式精講”系列的第5天,我們將深入講解原型模式(Prototype Pattern)。作為創建型設計模式之一,原型模式通過復制已有對象來創建新對象,避免了重復初始化和構造過程,提升了系統性能和靈活性。

原型模式的核心思想是:通過克隆已有的對象實例來創建新的對象,而不是通過構造函數或工廠方法進行實例化。它特別適用于那些構造成本較高、配置復雜的對象場景。在實際開發中,原型模式被廣泛應用于對象池、緩存、圖形界面組件復制等場景。

本文將從理論到實踐全面解析原型模式,包括其定義、結構、適用場景、實現方式、優缺點分析,并結合真實項目案例說明其應用價值。同時,我們還會探討其與其它設計模式的關系,并展示在Java標準庫中的實際應用。


模式定義

原型模式是一種創建型設計模式,它通過復制一個已有對象(即原型)來創建新對象,而不是通過調用構造函數或工廠方法。該模式的核心思想是:通過克隆操作減少對象創建的開銷,提高系統效率

原型模式的關鍵在于提供一個可以被復制的對象接口,通常通過實現 Cloneable 接口并重寫 clone() 方法來實現。在 Java 中,Object 類提供了 clone() 方法,但默認是淺拷貝(Shallow Copy),如果需要深拷貝(Deep Copy),則需要手動實現。


模式結構

原型模式的 UML 類圖包含以下幾個關鍵角色:

  • Prototype(原型類):聲明一個克隆自身的方法(通常是 clone())。
  • ConcretePrototype(具體原型類):實現 clone() 方法,返回自身的一個副本。
  • Client(客戶端):使用原型對象來創建新的對象,而不是直接使用構造函數。

文字描述如下:

  1. Prototype 是一個抽象類或接口,定義了 clone() 方法。
  2. ConcretePrototype 是實現了 clone() 方法的具體類,負責生成自身的副本。
  3. Client 調用 clone() 方法來創建新對象,而無需顯式地調用構造函數。

適用場景

原型模式適用于以下幾種典型場景:

場景描述
構造成本高當對象的構造過程復雜、耗時較長時,使用克隆可以節省資源。
配置復雜對象的初始化需要多個參數或依賴關系,克隆可以避免重復配置。
動態配置需要根據運行時配置動態創建對象,克隆可以快速生成相似對象。
多種變體需要創建多個類似對象,且它們之間只有少量差異時,克隆比重新構造更高效。

例如,在圖形編輯器中,用戶可以通過拖拽一個圖形元素來復制它,此時就可以使用原型模式來實現快速復制功能。


實現方式

下面是一個完整的 Java 示例,演示如何使用原型模式創建對象。

1. 定義原型接口
public interface Prototype extends Cloneable {Prototype clone();
}
2. 實現具體原型類
public class ConcretePrototype implements Prototype {private String name;private int value;public ConcretePrototype(String name, int value) {this.name = name;this.value = value;}// 淺拷貝實現@Overridepublic Prototype clone() {try {return (ConcretePrototype) super.clone();} catch (CloneNotSupportedException e) {throw new RuntimeException("克隆失敗", e);}}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getValue() {return value;}public void setValue(int value) {this.value = value;}@Overridepublic String toString() {return "ConcretePrototype{name='" + name + "', value=" + value + "}";}
}
3. 客戶端代碼示例
public class Client {public static void main(String[] args) {ConcretePrototype prototype = new ConcretePrototype("原型對象", 100);// 克隆對象ConcretePrototype cloned = (ConcretePrototype) prototype.clone();cloned.setName("克隆對象");cloned.setValue(200);System.out.println("原始對象: " + prototype);System.out.println("克隆對象: " + cloned);}
}

輸出結果:

原始對象: ConcretePrototype{name='原型對象', value=100}
克隆對象: ConcretePrototype{name='克隆對象', value=200}
4. 深拷貝實現(可選)

如果對象內部有引用類型字段,需要手動實現深拷貝:

public class DeepPrototype implements Prototype {private String name;private int value;private List<String> tags;public DeepPrototype(String name, int value, List<String> tags) {this.name = name;this.value = value;this.tags = new ArrayList<>(tags); // 淺拷貝}@Overridepublic Prototype clone() {DeepPrototype clone = new DeepPrototype(this.name, this.value, new ArrayList<>());clone.tags.addAll(this.tags); // 深拷貝return clone;}// 省略 getter/setter 和 toString 方法
}

工作原理

原型模式的核心機制是對象的復制,而非傳統的構造過程。通過調用 clone() 方法,可以快速生成一個與原對象相同狀態的新對象。

這種機制的優勢在于:

  • 避免重復初始化:不需要每次都重新執行構造邏輯,尤其適用于構造復雜、資源消耗大的對象。
  • 提高性能:在某些場景下,克隆操作比重新構造對象更快。
  • 簡化對象創建流程:客戶端只需知道一個原型對象即可創建多個相似對象,降低了耦合度。

優缺點分析

優點缺點
提高對象創建效率,避免重復初始化如果對象內部包含復雜引用結構,深拷貝實現較為復雜
減少對構造函數的依賴,降低耦合不適合所有場景,尤其是需要嚴格控制對象生命周期的情況
易于擴展,支持多種變體對象可能導致對象狀態不一致,特別是當原型對象被修改后

案例分析:圖形編輯器中的對象復制

假設我們正在開發一個圖形編輯器,用戶可以繪制矩形、圓形等圖形,并能夠通過拖拽復制圖形。如果每次復制都重新創建圖形對象,會浪費大量資源,尤其是在圖形數量較多時。

問題:

  • 每次復制都需要重新設置圖形的屬性(如位置、大小、顏色等)。
  • 重復構造圖形對象,增加內存和計算開銷。

解決方案:

  • 使用原型模式,讓圖形類實現 clone() 方法。
  • 用戶點擊復制按鈕時,調用圖形對象的 clone() 方法,生成一個新的圖形副本。
  • 新圖形對象繼承原圖形的所有屬性,僅需調整位置即可。

代碼示例:

public abstract class Shape implements Prototype {protected String color;public Shape(String color) {this.color = color;}public abstract void draw();@Overridepublic abstract Shape clone();
}public class Rectangle extends Shape {private int width;private int height;public Rectangle(String color, int width, int height) {super(color);this.width = width;this.height = height;}@Overridepublic void draw() {System.out.println("繪制矩形,顏色:" + color + ", 寬:" + width + ", 高:" + height);}@Overridepublic Rectangle clone() {return new Rectangle(this.color, this.width, this.height);}
}

客戶端使用:

public class Editor {public static void main(String[] args) {Shape original = new Rectangle("紅色", 100, 50);Shape copy = original.clone();original.draw();  // 輸出:繪制矩形,顏色:紅色, 寬:100, 高:50copy.draw();      // 輸出:繪制矩形,顏色:紅色, 寬:100, 高:50}
}

與其他模式的關系

原型模式常與以下模式結合使用:

模式關系說明
工廠模式原型模式可以看作是工廠模式的一種替代方案,特別是在對象構造復雜時。
建造者模式兩者都可以用于創建復雜對象,但建造者關注的是分步驟構建,原型關注的是復制已有對象。
單例模式在某些場景下,原型模式可以與單例模式結合使用,確保只有一份原型對象被共享。

此外,原型模式還可以與享元模式結合使用,用于創建共享的、可復用的對象實例。


總結

原型模式是一種高效的創建型設計模式,通過復制已有對象來創建新對象,避免了重復構造和初始化過程。它適用于構造成本高、配置復雜的對象場景,具有良好的靈活性和擴展性。

在本篇文章中,我們詳細介紹了原型模式的定義、結構、實現方式、工作原理、優缺點以及實際應用場景。通過 Java 代碼示例,我們展示了如何在實際項目中使用原型模式,并討論了其與其它設計模式的關系。

下一節我們將進入“設計模式精講”的第6天,講解適配器模式(Adapter Pattern),它是結構型設計模式中非常重要的一個模式,主要用于解決接口不兼容的問題。


文章標簽

design-patterns, java, software-engineering, oop, object-oriented-programming, design-pattern-day5, prototype-pattern


文章簡述

在“設計模式精講”系列的第5天,我們深入講解了原型模式(Prototype Pattern),這是一種通過復制已有對象來創建新對象的創建型設計模式。文章從理論到實踐全面解析了該模式的定義、結構、適用場景、實現方式,并結合真實項目案例說明其應用價值。我們還通過完整的 Java 代碼示例展示了原型模式的實現過程,包括淺拷貝與深拷貝的區別,以及如何在圖形編輯器等實際場景中使用該模式。最后,我們分析了原型模式與其他設計模式的關系,并總結了其優缺點。通過本文的學習,讀者將掌握如何在實際項目中高效地使用原型模式,提升系統的性能和可維護性。


進一步學習資料

  1. Design Patterns: Elements of Reusable Object-Oriented Software
  2. Java Design Patterns - A Hands-On Guide with Examples
  3. Refactoring Guru - Prototype Pattern
  4. Java Documentation - Object.clone()
  5. GeeksforGeeks - Prototype Design Pattern in Java

核心設計思想回顧

  • 原型模式通過復制已有對象來創建新對象,避免重復構造。
  • 適用于構造成本高、配置復雜的對象場景。
  • 在 Java 中可通過實現 Cloneable 接口并重寫 clone() 方法實現。
  • 支持淺拷貝與深拷貝兩種方式,需根據業務需求選擇。
  • 與工廠模式、建造者模式等結合使用,提升系統靈活性和可維護性。

在實際開發中,合理使用原型模式可以顯著提升系統性能,特別是在需要頻繁創建相似對象的場景中。

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

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

相關文章

深度學習——第2章習題2-1分析為什么平方損失函數不適用于分類問題

深度學習——第2章習題2-1 《神經網絡與深度學習》——邱錫鵬 2-1 分析為什么平方損失函數不適用于分類問題。 平方損失函數&#xff08;Quadratic Loss Function&#xff09;經常用在預測標簽y為實數值的任務中&#xff0c;定義為 L ( y , f ( x ; θ ) ) 1 2 ( y ? f (…

【Linux】運行腳本后打屏同時保存到本地

命令&#xff1a; sh run.sh 2>&1 | tee output.log sh run.sh 2>&1 | tee output_$(date "%Y%m%d%H%M").log作用&#xff1a;運行腳本&#xff0c;并同時將輸出&#xff08;包括標準輸出和錯誤輸出&#xff09;顯示到終端&#xff0c;并保存到文件中…

Spark 在小眾日常場景中的實戰應用:從小店數據到社區活動

Spark 在小眾日常場景中的實戰應用&#xff1a;從小店數據到社區活動? 提起 Spark&#xff0c;大家往往會聯想到大型互聯網公司的數據處理、金融行業的復雜分析。但實際上&#xff0c;Spark 在許多小眾、貼近生活的場景中也能大顯身手。結合學習與實踐&#xff0c;我探索了 S…

mysql 執行計劃 explain命令 詳解

explain id &#xff1a;select查詢的序列號&#xff0c;包含一組數字&#xff0c;表示查詢中執行select子句或操作表的順序select_type&#xff1a;查詢類型 或者是 其他操作類型table &#xff1a;正在訪問哪個表partitions &#xff1a;匹配的分區type &#xff1a;訪問的類…

讓大模型“更懂人話”:對齊訓練(RLHF DPO)全流程實戰解析

網羅開發 &#xff08;小紅書、快手、視頻號同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企業從事人工智能項目研發管理工作&#xff0c;平時熱衷于分享各種編程領域的軟硬技能知識以及前沿技術&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

GO 原子操作面試題及參考答案

Go 的 sync/atomic 包和 sync.Mutex 的根本區別是什么&#xff1f; Go 語言中的 sync/atomic 包和 sync.Mutex 都用于處理并發編程中的同步問題&#xff0c;但它們的實現機制、應用場景和性能特性存在根本差異。理解這些差異對于編寫高效、安全的并發代碼至關重要。 sync/atomi…

MATLAB 山脊圖繪制全解析:從數據生成到可視化進階

一、引言&#xff1a;當數據分布擁有「層次感」—— 山脊圖的魅力? 在數據可視化的世界里&#xff0c;我們常常需要同時展示多個分布的形態差異。傳統的重疊密度圖雖然能呈現整體趨勢&#xff0c;但當分布數量較多時&#xff0c;曲線交疊會讓畫面變得雜亂。這時候&#xff0c…

跨境電商每周資訊—6.16-6.20

1. Instagram 在亞太地區逐漸超越 TikTok 在整個亞太地區&#xff0c;Instagram用戶數量正逐漸超過TikTok。預計2025年日本Instagram用戶數量將增至4440萬&#xff0c;印度今年用戶數量將增長10%&#xff0c;領跑亞太。與之形成對比的是&#xff0c;TikTok在一些國家增長速度放…

計算機網絡 網絡層:數據平面(一)

前一節學習了運輸層依賴于網絡層的主機到主機的通信服務&#xff0c;提供各種形式的進程到進程的通信。了解這種主機到主機通信服務的真實情況&#xff0c;是什么使得它工作起來的。 在本章和下一章&#xff0c;將學習網絡層實際是怎樣實現主機到主機的通信服務。與運輸層和應用…

Suna本地部署詳細教程

一、安裝基礎環境 # 1、創建環境 conda create -n suna python3.11.7# 2、激活虛擬環境 conda activate suna# 3、安裝jupyter和ipykernel pip install jupyter ipykernel# 4、將虛擬環境添加到jupyter # python -m ipykernel install --user --namemyenv --display-name"…

LeetCode 每日一題打卡|若谷的刷題日記 3day--最長連續序列

1.最長連續序列 題目&#xff1a; 給定一個未排序的整數數組 nums &#xff0c;找出數字連續的最長序列&#xff08;不要求序列元素在原數組中連續&#xff09;的長度。 請你設計并實現時間復雜度為 O(n) 的算法解決此問題。 示例 1&#xff1a; 輸入&#xff1a;nums [1…

EfficientVLA:面向視覺-語言-動作模型無訓練的加速與壓縮

25年6月來自上海交大、哈工大、西安交大和電子科大&#xff08;成都&#xff09;的論文“EfficientVLA: Training-Free Acceleration and Compression for Vision-Language-Action Models”。 視覺-語言-動作 (VLA) 模型&#xff0c;特別是基于擴散的架構&#xff0c;展現出具…

wireshark抓包分析TCP數據包

1、直接從TCP的三次握手開始說起 三次握手就是客戶與服務器建立連接的過程 客戶向服務器發送SYN(SEQ=x)報文,然后就會進入SYN_SEND狀態服務器收到SYN報文之后,回應一個SYN(SEQ=y)ACK(ACK=x+1)報文,然后就會進入SYN_RECV狀態客戶收到服務器的SYN報文,回應一個ACK(AC…

同等學力申碩-計算機統考-歷年真題和備考經驗

同等學力申請碩士學位考試是比較適合在職人員的提升學位方式&#xff0c;了解過的人應該都知道&#xff0c;現在社會的競爭壓力越來越大&#xff0c;為了提高職業生存能力&#xff0c;提升學位在所難免。 一、已有計算機統考歷年真題資料 報名過同等學力申碩計算機專業的朋友都…

OSI網絡通信模型詳解

OSI 模型就是把這整個過程拆解成了 7 個明確分工的步驟&#xff0c;每一層只負責自己那一攤事兒&#xff0c;這樣整個系統才能順暢運轉&#xff0c;出了問題也容易找到“鍋”在誰那。 核心比喻&#xff1a;寄快遞 &#x1f4e6; 想象你要把一份重要的禮物&#xff08;你的數據…

C++ 檢測文件大小和文件傳輸

檢測文件的大小 你可以通過標準 C/C 的文件 API 很方便地獲取文件的字節大小&#xff0c;以下是幾種常用方法&#xff1a; ? 方法一&#xff1a;使用 stat() 函數&#xff08;推薦&#xff09; #include <sys/stat.h> #include <stdio.h>off_t get_file_size(co…

Ubuntu 中修改網卡 IP

在 Ubuntu 中修改網卡 IP 地址可以通過以下方法實現&#xff0c;具體取決于你使用的網絡管理工具&#xff08;如 netplan、ifconfig/ip 命令或傳統 interfaces 文件&#xff09;。以下是常見方法&#xff1a; 方法 1&#xff1a;使用 netplan&#xff08;Ubuntu 17.10 及更新版…

記錄學習three.js 為什么 .glTF 是更適合 Web 的 3D 模型格式?——從 .OBJ 到 .glTF 的轉變?

在上一篇中&#xff0c;我們介紹了如何在 Three.js 中加載 .OBJ 模型。如果你沒看過&#xff0c;建議先閱讀一下基礎內容。然而你很快會發現&#xff0c;.OBJ 雖然入門簡單&#xff0c;卻并不是 Web3D 場景中的最佳格式。 .OBJ 是什么&#xff1f; .OBJ 是最早期的3D交換格式之…

H遞歸函數.go

前言&#xff1a;遞歸函數是一種強大而又充滿魅力的編程技巧。它就像是一面神奇的鏡子&#xff0c;函數在其中能夠調用自身的倒影&#xff0c;從而以一種簡潔而優雅的方式解決許多復雜的問題。 目錄 一、遞歸函數是啥玩意兒 二、遞歸函數的優缺點 優點 缺點 三、遞歸函數…

軟件功能測試的測試標準

一、軟件功能測試行業標準概述 軟件功能測試行業標準是規范軟件測試流程、方法、工具及人員資質的準則&#xff0c;是確保軟件產品的功能性、可靠性、易用性等質量特性符合用戶需求。這些標準不僅為測試人員提供了明確的指導&#xff0c;也為軟件產品的質量控制提供了有力保障。…