原型模式簡述
定義: 使用原型實例指定待建立對象的類型,而且經過複製這個原型來建立新的對象
,也就是經過複製現有對象實例產生新的對象,也就是所謂的「克隆」java
實現方式:數組
一、實現Cloneable接口安全
Cloneable接口的做用是在運行時通知虛擬機能夠安全地在實現了此接口的類上使用clone方法。在java虛擬機中,只有實現了這個接口的類才能夠被拷貝,不然在運行時會拋出CloneNotSupportedException異常。ide
二、重寫Object的clone方法函數
Java中,全部類的父類都是Object類,Object類中有一個clone方法,返回對象的一個拷貝,可是其做用域protected類型的,通常的類沒法調用,所以,原型類須要將clone方法的做用域修改成public類型。測試
原型模式結構
原型模式包含3個角色:this
1)Prototype(抽象原型類):聲明克隆方法的抽象類或接口,是全部具體原型類的父類spa
2)ConcretePrototype(具體原型類):實現抽象原型類聲明的克隆方法,實現自我克隆的功能code
3)Client(客戶端):請求原型對象克隆自身從而建立一個新的對象對象
代碼事例
/** * 抽象原型類 * * @author kaifeng * @date 2018/8/26 */ public abstract class Prototype implements Cloneable { /** * 獲取名稱 * * @return */ public abstract String getName(); /** * 抽象拷貝方法 * * @return Object * @throws CloneNotSupportedException */ public abstract Object copy() throws CloneNotSupportedException; } /** * 具體原型類One * * @author kaifeng * @date 2018/8/26 */ public class ConcretePrototypeOne extends Prototype { private String name; public ConcretePrototypeOne(String name) { this.name = name; } /** * 獲取名稱 * * @return */ @Override public String getName() { return this.name; } /** * 抽象拷貝方法 * * @return Object * @throws CloneNotSupportedException */ @Override public Object copy() throws CloneNotSupportedException { return super.clone(); } } /** * 具體原型類Two * * @author kaifeng * @date 2018/8/26 */ public class ConcretePrototypeTwo extends Prototype { private String name; public ConcretePrototypeTwo(String name) { this.name = name; } /** * 獲取名稱 * * @return */ @Override public String getName() { return this.name; } /** * 抽象拷貝方法 * * @return Object * @throws CloneNotSupportedException */ @Override public Object copy() throws CloneNotSupportedException { return super.clone(); } } /** * 原型模式測試 * * @author kaifeng * @date 2018/8/26 */ public class ProtoTypeDemo { public static void main(String[] args) throws CloneNotSupportedException { Prototype p1 = new ConcretePrototypeTwo("two"); System.out.println(p1.getName()); Prototype p2 = (ConcretePrototypeTwo) p1.copy(); System.out.println(p2.getName()); } }
優勢
一、隱藏了製造新實例的複雜性,使得建立對象就像咱們在編輯文檔時的複製粘貼同樣簡單
二、當建立對象的實例較爲複雜的時候,使用原型模式能夠簡化對象的建立過程,經過複製一個已有的實例能夠提升實例的建立效率。
缺點
一、因爲使用原型模式複製對象時不會調用類的構造方法,因此原型模式沒法和單例模式組合使用,由於原型類須要將clone方法的做用域修改成public類型,那麼單例模式的條件就沒法知足了。
二、Object類的clone方法只會拷貝對象中的基本數據類型,對於數組,引用對象等只能另行拷貝
適用場景
一、若是建立新對象成本較大,咱們能夠利用已有的對象進行復制來得到。
二、若是系統要保存對象的狀態,而對象的狀態變化很小,或者對象自己佔內存不大的時候,也能夠使用原型模式配合備忘錄模式來應用。相反,若是對象的狀態變化很大,或者對象佔用的內存很大,那麼採用狀態模式會比原型模式更好。
三、須要避免使用分層次的工廠類來建立分層次的對象,而且類的實例對象只有一個或不多的幾個組合狀態,經過複製原型對象獲得新實例可能比使用構造函數建立一個新實例更加方便。
深拷貝(克隆)與淺拷貝(克隆)
淺拷貝:
一個對象複製後,基本數據類型的變量都會從新建立,而引用類型,指向的仍是原對象所指向的。
深拷貝:
一個對象複製後,不管是基本數據類型還有引用類型,都是從新建立的。
java 的clone克隆是淺克隆,對於引用對象,克隆出來的對象和原對象中的引用將指向同一個對象。一般實現深克隆的方法是將對象進行序列化,而後再進行反序列化。