設計模式(建立型)之原型模式(Prototype Pattern),prototypepattern
PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown文法了,牛逼啊!
【工匠若水 http://blog.csdn.net/yanbober】 閱讀前一篇《設計模式(建立型)之建造者模式(Builder Pattern)》 http://blog.csdn.net/yanbober/article/details/45338041
概述
要理解原型原型模式必須先理解Java裡的淺複製和深複製。有的地方,複製也叫做複製。Java提供這兩種複製方式。 因為Java中的提供clone()方法來實現對象的複製,所以Prototype模式實現一下子變得很簡單。
淺複製:被複製對象的所有變數都含有與原來的對象相同的值,而它所有的對其他對象的引用都仍然指向原來的對象。換一種說法就是淺複製僅僅複製所考慮的對象,而不複製它所引用的對象。
深複製:被複製對象的所有變數都含有與原來的對象相同的值,但它所有的對其他對象的引用不再是原有的,而這是指向被複製過的新對象。換言之,深複製把要複製的對象的所有引用的對象都複製了一遍,這種叫做間接複製。
複製必須滿足的條件:
在java中實現clone()應該滿足以上三個條件(前兩個是必須的,第三個是推薦但不強制的)。
核心
概念: 使用原型執行個體指定建立對象的種類,並且通過拷貝這些原型建立新的對象。原型模式是一種對象建立型模式。
重點: 原型模式結構重要核心模組:
實現Cloneable介面
在java語言有一個Cloneable介面,它的作用只有一個,就是在運行時通知虛擬機器可以安全地在實現了此介面的類上使用clone方法。在java虛擬機器中,只有實現了這個介面的類才可以被拷貝,否則在運行時會拋出CloneNotSupportedException異常。
重寫Object類中的clone方法
Java中,所有類的父類都是Object類,Object類中有一個clone方法,作用是返回對象的一個拷貝,但是其範圍protected類型的,一般的類無法調用,因此,Prototype類需要將clone方法的範圍修改為public類型。
使用情境
建立新對象成本較大(如初始化需要佔用較長的時間,佔用太多的CPU資源或網路資源),新的對象可以通過原型模式對已有對象進行複製來獲得,如果是相似對象,則可以對其成員變數稍作修改。
如果系統要儲存對象的狀態,而對象的狀態變化很小,或者對象本身佔用記憶體較少時,可以使用原型模式配合備忘錄模式來實現。
需要避免使用分層次的工廠類來建立分層次的對象,並且類的執行個體對象只有一個或很少的幾個組合狀態,通過複製原型對象得到新執行個體可能比使用建構函式建立一個新執行個體更加方便。
程式猿執行個體
package yanbober.github.io;//實現Cloneable介面,重寫Object類中的clone方法class MonkeyPrototype implements Cloneable { @Override protected MonkeyPrototype clone() throws CloneNotSupportedException { MonkeyPrototype monkeyPrototype = (MonkeyPrototype) super.clone(); return monkeyPrototype; }}//原型模式實作類別class ConcreteMonkeyPrototype extends MonkeyPrototype { public void printHasCode() { System.out.println("ConcreteMonkeyPrototype hascode="+this.hashCode()); }}public class Main { public static void main(String[] args) { ConcreteMonkeyPrototype type = new ConcreteMonkeyPrototype(); type.printHasCode(); for (int index=0; index<5; index++) { try { ConcreteMonkeyPrototype clone = (ConcreteMonkeyPrototype) type.clone(); clone.printHasCode(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }}
運行結果:
ConcreteMonkeyPrototype hascode=356573597
ConcreteMonkeyPrototype hascode=1735600054
ConcreteMonkeyPrototype hascode=21685669
ConcreteMonkeyPrototype hascode=2133927002
ConcreteMonkeyPrototype hascode=1836019240
ConcreteMonkeyPrototype hascode=325040804
注意事項
使用原型模式複製對象不會調用類的構造方法
因為對象的複製是通過調用Object類的clone方法來完成的,它直接在記憶體中複製資料,因此不會調用到類的構造方法。不但構造方法中的代碼不會執行,甚至連存取權限都對原型模式無效。還記得單例模式嗎?單例模式中,只要將構造方法的存取權限設定為private型,就可以實現單例。但是clone方法直接無視構造方法的許可權,所以,單例模式與原型模式是衝突的,在使用時要特別注意。
總結一把
原型模式優點如下:
- 當建立新的對象執行個體較為複雜時,可以簡化對象建立過程,通過複製一個已有執行個體可以提高執行個體的建立效率。
- 擴充性較好,原型模式中提供了抽象原型類,在用戶端可以針對抽象原型類進行編程。
- 原型模式提供了簡化的建立結構,Factory 方法模式常常需要有一個與產品類等級結構相同的工廠等級結構,而原型模式就不需要這樣,原型模式中產品的複製是通過封裝在原型類中的複製方法實現的,無須專門的工廠類來建立產品。
- 可以使用深複製的方式儲存對象的狀態,使用原型模式將對象複製一份並將其狀態儲存起來,以便在需要的時候使用(如恢複到某一曆史狀態),可輔助實現撤銷操作。
原型模式缺點如下:
- 需要為每一個類配備一個複製方法,而且該複製方法位於一個類的內部,當對已有的類進行改造時違背“開閉原則”。
- 在實現深複製時需要編寫較為複雜的代碼,而且當對象之間存在多重的嵌套引用時,為了實現深複製,每一層對象對應的類都必須支援深複製比較麻煩。
【工匠若水 http://blog.csdn.net/yanbober】 繼續閱讀《設計模式(結構型)之適配器模式(Adapter Pattern)》 http://blog.csdn.net/yanbober/article/details/45338829