設計模式(四)原型模式


原型模式:通過new產生一個對象需要非常繁瑣的數據准備或訪問權限,則可以使用原型模式。就是java中的克隆技術,以某個對象為原型,復制出新的對象。顯然,新的對象具備原型對象的特點。

優勢:效率高(直接克隆,避免了重新執行構造步驟)。

克隆類似於new,但是不同於new。new創建新的對象屬性采用的是默認值。克隆出的對象的屬性值完全和原型對象相同。並且克隆出的新對象改變不會影響原型對象。然后,再修改克隆對象的值。


 

原型模式實現:

Cloneable接口和clone方法。

Prototype模式中實現起來最困難的地方就是內存復制操作,所幸在Java中提供了clone()方法替我們做了絕大部分事情。

 


 

淺復制和深復制:

例:淺復制

 定義一個Sheep類:

 1 package com.ztq.prototype;
 2 
 3 import java.util.Date;
 4 
 5 public class Sheep implements Cloneable{
 6     private String sname;
 7     private Date birthday;
 8     
 9     @Override
10     protected Object clone() throws CloneNotSupportedException {
11         Object obj = super.clone(); //直接調用Object對象的clone()方法
12         return obj;
13     }
14 
15     public String getSname() {
16         return sname;
17     }
18 
19     public void setSname(String sname) {
20         this.sname = sname;
21     }
22 
23     public Date getBirthday() {
24         return birthday;
25     }
26 
27     public void setBirthday(Date birthday) {
28         this.birthday = birthday;
29     }
30 
31     public Sheep(String sname, Date birthday) {
32         super();
33         this.sname = sname;
34         this.birthday = birthday;
35     }
36     
37     public Sheep(){}
38 }

測試類:

 1 package com.ztq.prototype;
 2 
 3 import java.util.Date;
 4 
 5 /***
 6  * 測試原型模式(淺復制)
 7  * @author ZTQ
 8  *
 9  */
10 public class Client2 {
11     public static void main(String[] args) throws CloneNotSupportedException {
12         Date date = new Date(123123123123L);
13         Sheep s1 = new Sheep("aa", date);
14         Sheep s2 = (Sheep)s1.clone();
15         
16         System.out.println(s1.getBirthday());
17         
18         date.setTime(234234234L);
19         
20         System.out.println(s1.getBirthday());
21         System.out.println(s2.getBirthday());
22     }
23 }

打印結果:

Mon Nov 26 08:52:03 GMT+08:00 1973
Sun Jan 04 01:03:54 GMT+08:00 1970
Sun Jan 04 01:03:54 GMT+08:00 1970

可見,s2克隆的s1,更改時間后,s2的birthday屬性也跟着改變了。

 

深復制:


將重新的clone方法中添加代碼:

 1 @Override
 2     protected Object clone() throws CloneNotSupportedException {
 3         Object obj = super.clone(); //直接調用Object對象的clone()方法
 4         
 5         //添加如下代碼實現深復制
 6         Sheep s = (Sheep)obj;
 7         s.birthday = (Date)this.birthday.clone();
 8         
 9         return obj;
10     }

打印結果:

Mon Nov 26 08:52:03 GMT+08:00 1973
Sun Jan 04 01:03:54 GMT+08:00 1970
Mon Nov 26 08:52:03 GMT+08:00 1973

時間改變后,s2的birthday屬性並沒有隨之改變。

 

序列化和反序列化實現深復制:

 1 public class Client2 {
 2     public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
 3         Date date = new Date(123123123123L);
 4         Sheep s1 = new Sheep("aa", date);
 5         System.out.println(s1);
 6         System.out.println(s1.getSname());
 7         System.out.println(s1.getBirthday());
 8 //        Sheep s2 = (Sheep)s1.clone();
 9 //        使用序列化和反序列化實現深復制
10         ByteArrayOutputStream bos = new ByteArrayOutputStream();
11         ObjectOutputStream oos = new ObjectOutputStream(bos);
12         oos.writeObject(s1);
13         byte[] bytes = bos.toByteArray();
14         
15         ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
16         ObjectInputStream ois = new ObjectInputStream(bis);
17         Sheep s2 = (Sheep)ois.readObject();  //克隆好的對象
18         
19         date.setTime(234234234L);  
20         
21         System.out.println(s1.getBirthday());
22         System.out.println(s2.getBirthday());
23     }

 打印結果:

com.ztq.prototype.Sheep@133c5982
aa
Mon Nov 26 08:52:03 GMT+08:00 1973
Sun Jan 04 01:03:54 GMT+08:00 1970
Mon Nov 26 08:52:03 GMT+08:00 1973

 

 

開發中的應用場景:

——原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過clone的方法創建一個對象,然后由工廠方法提供給調用者。

  spring中bean的創建實際就是兩種:單例模式和原型模式。(當然,原型模式需要和工廠模式搭配起來)

 

總結:

創建者模式:都是用來幫助我們創建對象的。

——單例模式:

  保證一個類只有一個實例,並且提供一個訪問該實例的全局訪問點。

——工廠模式:

  簡單工廠模式:用來生產同一等級結構中的任意產品。(對於增加新的產品,需要修改已有代碼)

  工廠方法模式:用來生產同一等級結構中的固定產品。(支持增加任意產品)

  抽象工廠模式:用來生產不同產品族的全部產品。(對於增加新的產品,無能為力;支持增加產品族)

——建造者模式:

  分離了對象子組件的單獨構造(由Builder來負責)和裝配(由Director負責),從而可以構造出復雜的對象。

——原型模式:

  通過new產生一個對象需要非常繁瑣的數據准備或訪問權限,則可以使用原型模式。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM