摘要:但是這種復制技術在的世界里早已出現,就是原型模式什么是原型模式用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象類圖原型模式是設計模式中最簡單的,沒有之一。
前言
在現實世界中,我們通常會感覺到分身乏術。要是自己有分身那該多好啊,一個用來工作,一個用來看電視,一個用來玩游戲(無意中透露了自己單身狗的身份-。-),其實就是克隆,這種技術存在著很大的弊端,所以現在是禁止使用的。但是這種復制技術在java的世界里早已出現,就是原型模式
什么是原型模式用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象
uml類圖原型模式是設計模式中最簡單的,沒有之一。因為它的核心就是一個clone方法,通過這個方法完成對象的克隆。java提供了cloneable接口來標示這個對象是有可能被克隆的,這個接口只具有標記作用,在jvm中只有具有這個標記的對象才有可能被克隆。有可能克隆變成可以被克隆,就需要我們重寫clone方法
淺拷貝public class Person implements Cloneable{ public Person() { System.out.println("構造函數執行了"); } private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } }
public class Client { public static void main(String[] args) throws CloneNotSupportedException { Person person = new Person(); person.setName("bin"); Person person1=person.clone(); person1.setName("123"); System.out.println(person.getName()+"---"+person1.getName()); } } 測試結果: 構造函數執行了 bin---123
通過以上例子可以得知,實現cloneable接口,復寫clone方法,即可對對象進行復制。有一個問題clone方法是怎么創建對象的?可以看到,構造函數只執行了一次,這就說明clone方法是不會調用構造函數的,它其實是內存二進制流的拷貝,比直接new對象性能要好很多。
標題是淺拷貝,那到底什么是淺拷貝呢?先不要著急,我們來改動下例子:
public class Person implements Cloneable{ private ListvalueList = new ArrayList<>(); public void setValue(){ valueList.add("1"); } public List getValue(){ return valueList; } @Override protected Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } }
public class Client { public static void main(String[] args) throws CloneNotSupportedException { Person person = new Person(); person.setValue(); Person person1=person.clone(); person1.setValue(); System.out.println(person1.getValue()); } } 測試過程: 構造函數執行了 [1, 1]
或許你會很費解明明進行了拷貝,應該只會打印一個“1”啊,,為什么person1.getValue()會打印出兩個“1”呢?因為java做了一個偷懶的拷貝動作,Object提供的clone方法只拷貝本對象,對其引用對象和內部數組都不拷貝,只是將地址拷貝過來用,這種拷貝方式就是淺拷貝。但是String對象例外,因為java本就希望將String看成基本數據類型,它沒有clone方法,并且它的處理機制非常特殊,通過字符串池在內存中創建新的字符串,我們只要把其看待成基本數據類型就可以了。
深拷貝當拷貝的對象中有引用對象或者數組時,我們通過淺拷貝獲得復制對象是不安全的。怎么解決呢?我們可以通過深拷貝來解決這個問題,下面繼續改造例子學習深拷貝:
public class Person implements Cloneable{ private ArrayListvalueList = new ArrayList<>(); public void setValue(){ valueList.add("1"); } public List getValue(){ return valueList; } @Override protected Person clone() throws CloneNotSupportedException { Person person=(Person) super.clone(); person.valueList= (ArrayList ) this.valueList.clone(); return person; } }
public class Client { public static void main(String[] args) throws CloneNotSupportedException { Person person = new Person(); person.setValue(); Person person1=person.clone(); person1.setValue(); System.out.println(person.getValue()); System.out.println(person1.getValue()); } } 測試結果: person:[1] person1[1, 1]
通過對引用對象和數組的進行獨立的拷貝,就完成了深拷貝,每個person對象都會有自己的valueList。
clone和final對象的clone和對象內的final是互相沖突的,下面我們來看個圖片:
當我們將valueList增加final關鍵字,對其clone編譯會報錯,解決辦法就是不要加final關鍵字(感覺像是廢話...)
原型模式和現實世界中說的克隆基本一樣。原型模式是內存二進制流的拷貝,比new對象性能高很多,尤其是當創建這個對象需要數據庫或者其他硬件資源時尤為明顯。另外我們需要注意的就是當復制的對象存在引用對象和數組時,要根據實際業務選擇深拷貝還是淺拷貝。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70834.html
摘要:如果一個對象的初始化需要很多其他對象的數據準備或其他資源的繁瑣計算,那么可以使用原型模式。當需要一個對象的大量公共信息,少量字段進行個性化設置的時候,也可以使用原型模式拷貝出現有對象的副本進行加工處理。 1、什么是原型模式Specify the kinds of objects to create using a prot...
摘要:三種使用構造函數創建對象的方法和的作用都是在某個特殊對象的作用域中調用函數。這種方式還支持向構造函數傳遞參數。叫法上把函數叫做構造函數,其他無區別適用情境可以在特殊的情況下用來為對象創建構造函數。 一、工廠模式 工廠模式:使用字面量和object構造函數會有很多重復代碼,在此基礎上改進showImg(https://segmentfault.com/img/bVbmKxb?w=456&...
摘要:繼續分享設計模式的公開課,這是第四篇創建型模式之原型模式設計模式的一般介紹在第一篇文章講了,不了解的可以先看看。設計模式的第一部分,創建型模式就總結完了。下面還有兩部分結構型設計模式和行為型設計模式稍后繼續。 繼續分享設計模式的公開課,這是第四篇創建型模式之原型模式 設計模式的一般介紹在第一篇文章講了,不了解的可以先看看。 原型模式: 用原型實例指定創建對象的種類,并且通過拷貝這個...
摘要:可以用刪除實例對象中自己添加的屬性可以確定屬性是原型中還是實例對象中,當時實例對象中時,返回的是操作符,有兩種使用方式,單獨使用和循環中。單獨使用,通過對象能夠訪問屬性時返回,無論時在原型中還是實例對象中。 原型模式,每個創建的對象都有一個prototype屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。 ------------...
摘要:深入系列第十四篇,講解創建對象的各種方式,以及優缺點。也就是說打著構造函數的幌子掛羊頭賣狗肉,你看創建的實例使用都無法指向構造函數這樣方法可以在特殊情況下使用。 JavaScript深入系列第十四篇,講解創建對象的各種方式,以及優缺點。 寫在前面 這篇文章講解創建對象的各種方式,以及優缺點。 但是注意: 這篇文章更像是筆記,因為《JavaScript高級程序設計》寫得真是太好了! 1....
閱讀 2779·2023-04-26 01:47
閱讀 3591·2023-04-25 23:45
閱讀 2461·2021-10-13 09:39
閱讀 606·2021-10-09 09:44
閱讀 1789·2021-09-22 15:59
閱讀 2761·2021-09-13 10:33
閱讀 1706·2021-09-03 10:30
閱讀 656·2019-08-30 15:53