《一天一模式》— 原型模式

1、原型模式的概念

原型模式(Prototype Pattern)是用於建立重複的對象,同時又能保證性能。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。 java

2、何時使用原型模式

原型模式能夠理解爲:以一個類做爲模板,克隆出無數個類,克隆出來的類與模板就再無關聯。設計模式

如下場景可使用原型模式:ide

  • 構造函數較複雜,或者不想使用構造函數建立對象;
  • 資源優化,在初始化時一個類時須要較多的資源,使用原型模式,初始化一次後,就進行克隆(不會再初始化);
  • 性能提高,使用克隆要比使用new建立一個對象的性能高,克隆直接在內存中操做二進制流,new則須要JVM作不少的準備(加載、驗證、準備、解析、初始化),因此在某些場景要大量建立相同對象時,能夠節約性能;

下面就以提高性能做爲場景,來用Java實現原型模式。函數

3、怎麼使用原型模式

3.1 實現方式

首先假設一個場景,中秋節將至,系統要爲所有的500萬(或者更多)用戶發送消息(一條條發,先不考慮其餘技術實現,主要爲了說明原型模式)。這種狀況下,若是貿然使用for循環來經過new關鍵字建立500萬個對象,假設new一個對象要花費0.04秒,那麼new500萬個也未必能在一天以內發送完畢。性能

這種狀況下就可使用原型模式來提高性能,下面看類圖和代碼:優化

代碼以下:spa

// 消息模板,繼承Cloneable接口
public interface MessageTemplate extends Cloneable {

    // 克隆消息
    MessageTemplate cloneMessage() throws CloneNotSupportedException;

}

// 消息
public class Message implements MessageTemplate {

    // 實現克隆方法
    public Message cloneMessage() throws CloneNotSupportedException {
        Message message;
        message = (Message) clone();
        return message;
    }

    @Override
    public String toString() {
        return "Message{" +
                "createTime=" + createTime +
                ", title='" + title + '\'' +
                ", context='" + context + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }

    // getter and setter ...

    private Date createTime;
    private String title;
    private String context;
    private String phone;


}

// 使用克隆模式
public class Client {

    public static void main(String[] args) throws CloneNotSupportedException {

        // 模擬發送消息,加入發送100萬個消息給不一樣用戶
        // 消息模板使用相同模板,消息內容有某些不一樣
        // 則可使用原型模式

        int count = 100; // 用戶數量,就不寫100萬了
        // 建立模板
        Message message = new Message();
        message.setTitle("節日關懷");
        message.setContext("尊敬的%s,您好。吧啦吧啦……");
        for (int i = 0; i < count; i++) {
            Message m = message.cloneMessage();
            m.setContext(String.format(message.getContext(), i));
            m.setPhone(i + "");
            m.setCreateTime(new Date());
            System.out.println(m.toString());
        }

    }

}

// 輸出
Message{createTime=Tue May 19 23:05:52 CST 2020, title='節日關懷', context='尊敬的0,您好。吧啦吧啦……', phone='0'}
Message{createTime=Tue May 19 23:05:52 CST 2020, title='節日關懷', context='尊敬的1,您好。吧啦吧啦……', phone='1'}
Message{createTime=Tue May 19 23:05:52 CST 2020, title='節日關懷', context='尊敬的2,您好。吧啦吧啦……', phone='2'}
......
Message{createTime=Tue May 19 23:05:52 CST 2020, title='節日關懷', context='尊敬的98,您好。吧啦吧啦……', phone='98'}
Message{createTime=Tue May 19 23:05:52 CST 2020, title='節日關懷', context='尊敬的99,您好。吧啦吧啦……', phone='99'}

上面的代碼就是原型模式的作法和用法。設計

核心就是使用了Java中Object對象自帶的clone方法,來完成類的克隆。指針

這裏須要注意的是Cloneable接口,它比較特別,clone方法並非它定義的,它只是用來描述對象可使用clone方法,是一種標記接口。code

3.2 原型模式的好處

原型模式的好處,就體現他的使用場景:

  • 構造函數較複雜,或者不想使用構造函數建立對象;
  • 資源優化,在初始化時一個類時須要較多的資源;
  • 性能提高,使用克隆要比使用new建立一個對象的性能高;

3.3 注意事項

原型模式的注意事項,主要強調兩點:

忽略構造函數:使用clone()方法,不會觸發對象的構造函數,若是類須要在構造函數中進行一些業務,則須要注意;

深拷貝:clone()方法會複製基本類型,可是引用類型複製的是引用的內存地址(指針),因此帶有引用類型的對象進行clone()時,須要處理深拷貝,網上有不少文章,就不在此敘述了;

4、總結

總的來講,原型模式屬於比較簡單的設計模式之一,也比較好理解,主要理清2點就能比較好的應用它:

使用場景:在何時適合用原型模式來建立對象;

技術實現:涉及到了使用cloneable接口,使用Object對象的clone方法,以及注意深拷貝

以上就是我對原型模式的一些理解,有不足之處請你們指出,謝謝。

相關文章
相關標籤/搜索