1. 程式人生 > >設計模式 _第七招式_原型模式

設計模式 _第七招式_原型模式

一、定義

用原型例項指定建立物件種類,並且通過拷貝這些原型建立新的物件。原型模式的核心是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 注意淺拷貝和深拷貝的區別
使用原型模式的時候,有一些類中的成員變數可能不會被拷貝。應用的成員變數必須滿足兩個條件才不會被拷貝。一是 類的成員變數,而不是方法內變數;二是必須是一個可變的引用物件,而不是一個不可變物件或原始型別。