設計模式 _第七招式_原型模式
一、定義
用原型例項指定建立物件種類,並且通過拷貝這些原型建立新的物件。原型模式的核心是clone方法,通過該方法進行物件的拷貝,Java提供了一個Cloneable介面來標示這物件是可以拷貝的,為什麼說是“標示”呢 ?JDK原始碼中Cloneable 介面是一個方法都沒有,這個介面只是一個標記的作用,在jvm中具有這個標識才可能被拷貝,且類中必須要重新clone()方法,覆寫了Object類中的clone方法。
二、程式碼演示
通過一個部門給不同的人員發相同內容的郵件為例,郵件裡面不同的是收件人地址,其它都是一樣的,通過clone產生公用屬性一直,特性不一致的的mail。
2.1 郵件類
public class Mail implements Cloneable { //收件人 private String receiver ; //郵件名稱 private String subject ; //稱謂 private String appellation ; //郵件內容 private String context; //郵件簽名 private String tail ; public String getReceiver() { return receiver; } public void setReceiver(String receiver) { this.receiver = receiver; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getAppellation() { return appellation; } public void setAppellation(String appellation) { this.appellation = appellation; } public String getContext() { return context; } public void setContext(String context) { this.context = context; } public String getTail() { return tail; } public void setTail(String tail) { this.tail = tail; } @Override public Mail clone(){ Mail mail = null ; try{ mail = (Mail)super.clone(); }catch (Exception e){ e.printStackTrace(); } return mail ; } @Override public String toString(){ String result = "Mail{"; result = result + "receiver:"+receiver + "|"; result = result + "appellation:"+appellation + "|"; result = result + "context:"+context + "|"; result = result + "}"; return result; } }
2.2 應用場景類
public class Client {
public static void main(String args[]){
Mail mails = new Mail();
mails.setContext("xx部門通告郵件");
mails.setAppellation("admin");
//下面傳送給不同的收件人
Mail mailNew1 = mails.clone();
mailNew1.setReceiver("[email protected]");
System.out.println(mailNew1.toString());
System.out.println("---------------------------------");
Mail mailNew2 = mails.clone();
mailNew2.setReceiver(" [email protected]");
System.out.println(mailNew2.toString());
}
}
結果:
Mail{receiver:[email protected]|appellation:admin|context:xx部門通告郵件|}
---------------------------------
Mail{receiver:[email protected]|appellation:admin|context:xx部門通告郵件|}
三、優點
3.1 效能優良
原型模式是在記憶體中通過二進位制流的拷貝,要比直接new一個物件效能要好,特別是要在一個迴圈體內產生大量的物件是,原型模式可以更好的體現其優點。
3.2 逃避建構函式約束
這既是它的優點也是缺點,直接在記憶體中拷貝,建構函式是不會執行的。有點事減少了約束,缺點是需要大家在實際應用中考慮。
四、缺點
4.1 可能有執行緒安全問題
在多執行緒環境下,多個執行緒公用一個物件本身是有執行緒安全隱患的, 這在實際專案中,需要著重考慮。
五、應用場景
5.1 優化資源場景
類初始化需要消化非常多的資源,這個資源包括數、硬體。
5.2 效能和安全要求的場景
通過new一個物件需要頻繁的準備資料或訪問許可權,則可以通過使用原型模式。
5.3 一個物件多個修改者場景
一個物件需要提供給其它的物件訪問,而且各個呼叫者可能都需要修改其值,可以用原型模式。
在實際專案中,原型模式單獨使用的很少,一般是和工廠模式一起出現,通過clone的方法建立一個物件,然後由工程方法提供給呼叫者。
六、注意事項
6.1 原型模式必備兩要素
A、實現Cloneable介面;B、重寫Object類clone方法;
6.2 建構函式不會被執行
6.3 注意淺拷貝和深拷貝的區別
使用原型模式的時候,有一些類中的成員變數可能不會被拷貝。應用的成員變數必須滿足兩個條件才不會被拷貝。一是 類的成員變數,而不是方法內變數;二是必須是一個可變的引用物件,而不是一個不可變物件或原始型別。