Java創造型模式之原型模式詳解

設計模式是面向對象設計中的一種標準方法,用于解決常見的設計問題。原型設計模式(Prototype Pattern)是23種經典設計模式之一,屬于創建型模式,它允許通過復制現有對象來創建新對象,而不是通過構造函數或工廠方法來創建。這樣,開發者可以在運行時通過復制原型對象來快速生成新的對象,極大地提高了程序的靈活性和性能。

本文將深入講解Java中的原型設計模式,解釋其概念、使用場景、以及如何在Java中實現。

一、原型設計模式的定義

原型模式是一種通過復制原型對象來創建新對象的設計模式。它使得對象的創建不依賴于具體的類構造,而是依賴于原型實例。原型實例通過淺拷貝或深拷貝的方式復制,從而生成新的實例對象。

關鍵點:

  1. 原型對象:一個可以復制的對象。
  2. 克隆操作:通過復制(克隆)原型對象來創建新的對象。
  3. 淺拷貝與深拷貝:淺拷貝指的是復制對象時,原對象和復制對象共享引用類型的成員變量。深拷貝則是完全復制對象,確保復制對象和原對象沒有任何共享的引用類型變量。

二、使用原型模式的原因

在某些場景中,傳統的對象創建方式可能過于復雜或不夠高效。通過原型模式,我們可以通過現有的對象(即原型)來快速創建新對象,而無需重新構造對象。

原型模式的優勢:

  1. 提高性能:當對象的創建過程比較復雜時,通過原型復制對象來創建新實例通常比使用構造函數更高效。
  2. 簡化創建過程:對象的創建不需要重復復雜的初始化操作,只需要通過復制已有對象來實現。
  3. 支持變更:通過復制原型對象,開發者可以在運行時修改對象的某些屬性,而不影響原對象。

適用場景:

  • 創建對象的過程較為復雜,且有多個相似對象需要頻繁創建時,原型模式尤其有效。
  • 需要在程序運行時動態創建大量相似對象的情況。
  • 在復制對象時不希望重復調用構造函數,特別是當對象初始化代價較大時。

三、原型模式的實現

在Java中,原型模式通常通過實現Cloneable接口來實現,Cloneable接口是Java標準庫中的一個標記接口,表示該對象支持克隆操作。Object類中的clone()方法是用于執行淺拷貝的默認實現。

1. 淺拷貝與深拷貝

  • 淺拷貝:復制對象時,只復制對象本身的基本數據類型成員,引用類型成員復制的是地址,意味著原對象和克隆對象會共享引用類型的成員。
  • 深拷貝:復制對象時,不僅復制對象本身,還會復制對象的引用類型成員,確保原對象和克隆對象互不影響。

2. 實現原型模式的步驟

步驟 1:實現 Cloneable 接口

首先,確保要復制的類實現了 Cloneable 接口。Cloneable接口是一個標記接口,它告訴Object.clone()方法該對象支持克隆操作。

步驟 2:重寫 clone() 方法

由于Object類的clone()方法是保護的(protected),我們需要在自己的類中覆蓋clone()方法。通常我們會將clone()方法設為public,以便外部可以調用。

步驟 3:深拷貝或淺拷貝

根據需求,可以在clone()方法中實現深拷貝或淺拷貝。默認的clone()方法是淺拷貝,如果需要深拷貝,需要手動實現。

四、Java中原型設計模式的示例代碼

1、淺拷貝

// 實現Cloneable接口
class Prototype implements Cloneable {private String name;private int age;// 構造方法public Prototype(String name, int age) {this.name = name;this.age = age;}// 獲取對象的淺拷貝@Overridepublic Prototype clone() {try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}// Getter和Setter方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Prototype{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class PrototypeDemo {public static void main(String[] args) {// 創建原型對象Prototype original = new Prototype("Alice", 30);System.out.println("Original Object: " + original);// 克隆原型對象Prototype clone = original.clone();System.out.println("Cloned Object: " + clone);// 修改克隆對象的屬性clone.setName("Bob");clone.setAge(25);System.out.println("Modified Cloned Object: " + clone);System.out.println("Original Object after modification: " + original);}
}

結果為:?

Original Object: Prototype{name='Alice', age=30}
Cloned Object: Prototype{name='Alice', age=30}
Modified Cloned Object: Prototype{name='Bob', age=25}
Original Object after modification: Prototype{name='Alice', age=30}

2、深拷貝

class Address {private String street;private String city;public Address(String street, String city) {this.street = street;this.city = city;}public Address(Address address) {this.street = address.street;this.city = address.city;}@Overridepublic String toString() {return "Address{" +"street='" + street + '\'' +", city='" + city + '\'' +'}';}
}class DeepPrototype implements Cloneable {private String name;private Address address;public DeepPrototype(String name, Address address) {this.name = name;this.address = address;}@Overridepublic DeepPrototype clone() {try {DeepPrototype cloned = (DeepPrototype) super.clone();cloned.address = new Address(this.address); // 深拷貝return cloned;} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}@Overridepublic String toString() {return "DeepPrototype{" +"name='" + name + '\'' +", address=" + address +'}';}
}public class DeepPrototypeDemo {public static void main(String[] args) {Address address = new Address("Baker Street", "London");DeepPrototype original = new DeepPrototype("John", address);System.out.println("Original Object: " + original);// 深拷貝原型對象DeepPrototype cloned = original.clone();System.out.println("Cloned Object: " + cloned);// 修改克隆對象的屬性cloned.address = new Address("Wall Street", "New York");System.out.println("Modified Cloned Object: " + cloned);System.out.println("Original Object after modification: " + original);}
}

結果為:

Original Object: DeepPrototype{name='John', address=Address{street='Baker Street', city='London'}}
Cloned Object: DeepPrototype{name='John', address=Address{street='Baker Street', city='London'}}
Modified Cloned Object: DeepPrototype{name='John', address=Address{street='Wall Street', city='New York'}}
Original Object after modification: DeepPrototype{name='John', address=Address{street='Baker Street', city='London'}}

五、總結

原型設計模式通過克隆現有對象來創建新對象,而不是每次都通過構造函數創建。這種方式非常適合需要頻繁創建相似對象的場景。Java提供了Cloneable接口和clone()方法來支持該模式的實現。在實際開發中,使用原型模式可以減少對象創建時的性能開銷,同時也可以在對象狀態變化時避免重復操作。

無論是淺拷貝還是深拷貝,原型模式都能有效提高開發效率,并在某些情況下避免不必要的資源浪費。理解并合理使用原型模式,可以在復雜系統的設計中發揮重要作用。

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

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

相關文章

python-leetcode 54.全排列

題目: 給定不含重復數字的數組nums,返回其所有可能的全排列,可以按任意順序返回答案 回溯法 一種通過探索所有可能的候選解來找出所有的解的算法。如果候選解被確認不是一個解(或者至少不是最后一個解),回溯算法會通…

python局部變量和全局變量

文章目錄 1.局部變量和全局變量2.局部變量2.1 局部變量的作用2.2 局部變量的生命周期 3. 全局變量3.1 函數不能直接修改全局變量的引用3.2 在函數內部修改全局變量的值3.3 全局變量定義的位置3.4 全局變量命名的建議 1.局部變量和全局變量 (1)局部變量 …

華為中小型企業項目案例

實驗目的(1) 熟悉華為交換機和路由器的應用場景 (2) 掌握華為交換機和路由器的配置方法 實驗拓撲實驗拓撲如圖所示。 華為中小型企業項目案例拓撲圖 實驗配置市場部和技術部的配置創建VLANLSW1的配置 [LSW1]vlan batch 10 20 [LSW1]q…

深度學習-簡介

一、幾個概念 (1)what is ai including? 看一張圖: 這里注意機器學習和深度學習的關系 (2)機器學習和模式識別有什么區別? 和機器學習同領域的有一個詞叫做模式識別,二者有什么區別呢? 機…

Unity小框架之單例模式基類

單例模式(Singleton Pattern)是一種常用的創建型設計模式,其核心目標是確保一個類只有一個實例,并提供一個全局訪問點。它常用于需要控制資源訪問、共享配置或管理全局狀態的場景(如數據庫連接池、日志管理器、應用配置…

安裝 Powerlevel10k 及 Oh My Zsh 的使用

1. 簡介 Powerlevel10k 是 Oh My Zsh 最流行的終端主題,它不僅美觀,還提供 Git 狀態顯示、命令執行時間、網絡狀態、Python 虛擬環境指示等 實用功能。相比其他主題,Powerlevel10k 速度更快、可定制性更強。 本教程將詳細介紹如何安裝 Powe…

verilog有符號數處理摘要

在FPGA設計中,一般的算數運算符都是按照無符號數進行的。那么需要有符號數計算的時候,該怎么辦呢? 很久很久以前也就是Verilog-2001還沒有出現時,是手動操作的,也就是說,對于一個8位的無符號數&#xff0c…

在IDEA中連接達夢數據庫:詳細配置指南

達夢數據庫(DM Database)作為國產關系型數據庫的代表,廣泛應用于企業級系統開發。本文將詳細介紹如何在IntelliJ IDEA中配置并連接達夢數據庫,助力開發者高效完成數據庫開發工作。 準備工作 1. 下載達夢JDBC驅動 訪問達夢官方資…

app.config.globalProperties

目錄 一:基礎使用 1、簡介 2、使用 3、打印結果: 二:封裝 1、創建一個.ts文件(utils/msg.ts) 2、在main.ts中全局注冊 3、在頁面中使用 4、打印結果 一:基礎使用 1、簡介 app.config.globalProperties 是 Vue 3 應用實例(app)的一個配置屬性&…

openai 標準化協議 Structured Outputs 具體示例教程

Structured Outputs 具體示例教程 場景:個人財務管理助手 假設我們要構建一個 AI 助手,幫助用戶記錄和管理個人財務支出。用戶可以輸入自然語言描述(如“昨天我花了50元買了午餐”),助手將提取關鍵信息并以結構化 JS…

16.使用讀寫包操作Excel文件:XlsxWriter 包

一 XlsxWriter 的介紹 XlsxWriter 只能寫入 Excel 文件。 OpenPyXL 和 XlsxWriter 的區別在筆記 15 。 二 如何使用 XlsxWriter 1.導包 import datetime as dtimport xlsxwriterimport excel 2.實例化工作簿 book xlsxwriter.Workbook("xlxswriter.xlsx") book.clo…

ChatGPT and Claude國內使用站點

RawChat kelaode chatgptplus chatopens(4.o mini免費,plus收費) 網頁: 定價: wildcard 網頁: 虛擬卡定價: 2233.ai 網頁: 定價: MaynorAPI chatgpt cla…

【MySQL】MySQL審計工具Audit Plugin安裝使用

MySQL審計工具Audit Plugin安裝使用 https://www.cnblogs.com/waynechou/p/mysql_audit.html MySQL 5.6 開啟審計功能 https://blog.51cto.com/u_15127556/4344503 MySQL之添加日志審計功能 https://blog.csdn.net/weixin_43279032/article/details/105507170 MySQL開啟日志記錄…

QT 磁盤文件 教程04-創建目錄、刪除目錄、遍歷目錄

【1】新建目錄 bool CreateDir(QString name){QString fileName name ;QDir dir(fileName);if (dir.isEmpty()) {dir.mkdir(fileName);return true;}else{qDebug()<<"文件夾已存在";return false;} } 【2】刪除目錄 bool DeleteDir(QString fileName){if (…

Git——分布式版本控制工具使用教程

本文主要介紹兩種版本控制工具——SVN和Git的概念&#xff0c;接著會講到Git的安裝&#xff0c;Git常用的命令&#xff0c;以及怎么在Vscode中使用Git。幫助新手小白快速上手Git。 1. SVN和Git介紹 1.1 SVN 集中式版本控制工具&#xff0c;版本庫是集中存放在中央服務器的&am…

Vue:添加響應式數據

Vue&#xff1a;添加響應式數據 1. 什么是響應式&#xff1f; 修改 data 后&#xff0c;頁面自動改變/刷新&#xff0c;這就是響應式。就像我們在使用 Excel 的時候&#xff0c;修改一個單元格中的數據&#xff0c;其它單元格的數據會聯動更新&#xff0c;這也是響應式。在前…

算法刷題記錄——LeetCode篇(10) [第901~1000題](持續更新)

(優先整理熱門100及面試150&#xff0c;不定期持續更新&#xff0c;歡迎關注) 994. 腐爛的橘子 在給定的 m x n 網格 grid 中&#xff0c;每個單元格可以有以下三個值之一&#xff1a; 值 0 代表空單元格&#xff1b;值 1 代表新鮮橘子&#xff1b;值 2 代表腐爛的橘子。 每…

Secs/Gem第二講 (基于secs4net項目的ChatGpt介紹)

好的&#xff0c;我們正式進入&#xff1a; 第二講&#xff1a;深入 SECS4NET 項目結構——主機程序是怎么搭起來的&#xff1f; 關鍵詞&#xff1a;項目結構、類圖、通信類、事件處理、連接生命周期、異步機制 本講目的 我們從源碼入手&#xff0c;一步步搞懂&#xff1a; S…

壓測實戰 | 微信小程序商城 “雙 11” 的壓測實踐

背景 某全球知名珠寶品牌&#xff0c;始終以創新驅動零售變革。隨著全渠道戰略的深化&#xff0c;其小程序官方商城逐漸成為品牌私域流量的核心陣地&#xff0c;不僅承載了線上銷售、會員運營等功能&#xff0c;同時還與其內部系統打通&#xff0c;如會員管理系統、人力資源系…

垃圾分類--環境配置

寫在前面&#xff1a; 如果你們打這屆比賽時&#xff0c;還有我們所保留的內存卡&#xff0c;那么插上即可運行&#xff08;因為內存卡里我們已經配置好所有的環境&#xff09; 本文提供兩種環境的配置 一種是基于yolov8&#xff1a;YOLOv8 - Ultralytics YOLO Docshttps://d…