標簽: 設計模式初涉
使用場景
簡單點說就是克隆對象!適用場景如下:
- 1.當初始化類對象需要消耗非常多資源,或者說要進行繁瑣
的數據準備或者權限,如果想簡化創建,可以使用原型模式。 - 2.一個對象提供給其他對象訪問,而各個調用者可能都需要
修改對象的值,可以考慮使用原型模式克隆多個對象供調用者
使用(保護性拷貝)
組成部分(三個角色):
-
Prototype —— 聲明一個克隆自身的接口,用于約束想要
克隆自己的類,要求實現定義的克隆方法。 -
ConcretePrototype —— 實現Prototype接口的類,這些類
真正實現克隆自身的相關代碼。 - Client —— 客戶端用戶,調用類
UML類圖如下:

Java中的 == 與 equals 的區別
==,如果是對比的基本數據類型(int,long等),比較存儲的值是否相等,
如果對比的是引用型的變量,比較的是所指向的對象地址是否相等equals,不能用于比較基本數據類型,如果沒對equals()方法進行
重寫,比較的是指向的對象地址,如果想要比較對象內容,需要自行重寫
方法,做相應的判斷!!!!String調equals是可以判斷內容是否一樣,是
因為對equals()方法進行了重寫,具體自己參見源碼!
克隆必須滿足的條件(三個)
- 1.對任何的對象x,都有:x.clone()!=x ,即不是同一對象、
- 2.對任何的對象x,都有:x.clone().getClass==x.getClass(),即對象類型一致
- 3.如果對象obj的equals()方法定義恰當的話,那么obj.clone().equals(obj)
應當是成立的。(推薦,不強制)
Java中如何使用:
Prototype原型類(想被克隆的類)實現Cloneable接口,重寫clone()方法。
調用:
ConcretePrototype cp1 = new ConcretePrototype();
ConcretePrototype cp2 = (ConcretePrototype)cp1.clone();
示例代碼
通過一個示例代碼來學習用法,以及驗證一些疑問
1.供引用的類:Money.java

2.實現Cloneable接口的類:Assets.java,核心就是重寫clone方法而已

3.調用類:Wealth.java

運行結果:

結果分析得出結論:
- 1.執行克隆方法,不會調用構造方法
- 2.克隆會生成的新的對象變量,指向的卻是同一個內存地址!
- 3.克隆前后數據類型一致!
- 4.克隆的時候,類中基本數據類型的屬性會新建,但是引用類型的
只會生成個新的引用變量,引用變量的地址依舊指向同一個內存地址!
深淺拷貝與實現深拷貝的兩種簡單套路
上面這種只新建基本類型數據,不新建引用類型數據,稱為淺拷貝,
如果連引用類型數據也新建的話,則稱為深拷貝。
深拷貝的其中一種實現套路是,引用類型也實現Cloneable接口,然后實現clone方法
比如讓Money類也實現Cloneable接口,重寫clone方法:

然后Assets類,clone方法那里調這個方法,為money對象賦值:

再運行一遍,運行結果:

好的,結果創建了新的對象,沒毛病,另外這種方法實現深拷貝
如果屬性的類型也是對象,那么需要一直遞歸的克隆下去!!
要想深度克隆成功,必須要整個克隆所涉及的對象都要正確實
現克隆方法,如果其中有一個沒有正確實現克隆,那么就會導致克隆失敗。
這就是深拷貝的其中一種實現套路,還有另一種套路是 序列化,
屬性的類型是引用類型的話,需要實現Serializable接口,
然后自己寫個方法來在里面完成對象轉二進制流與二進制流轉
對象的方法,然后返回克隆后的對象!



輸出結果和上面一致。
優缺點
優點:
- 1.簡化對象創建過程,當對象創建比較煩瑣時,可提高創建效率
- 2.深拷貝可保存對象狀態,可將對象拷貝后保存起來,需要的時候恢復
缺點:
- 1.深拷貝時,屬性存在引用類型多層嵌套的話,為了實現深克隆,每一層
對象對應的類都必須支持深克隆,實現起來可能會比較麻煩
本節代碼:
https://github.com/coder-pig/DesignPatternsExample/tree/master/3.Prototype%20Pattern