1. 程式人生 > >淺析設計模式(八)——創建型模式之Prototype(原型模式)

淺析設計模式(八)——創建型模式之Prototype(原型模式)

ref rri head 創建型模式 obj www str 操作 接口

原型模式Prototype

本文的內容:

  • 一、原型模式的定義
  • 二、原型模式的參與者及其角色

  • 三、原型模式的類圖

  • 四、原型模式的示例

  • 五、參考

一、原型模式的定義

  定義:用原型實例指定創建對象的實例,並且通過拷貝這些原型創建新的對象。

  使用現有的對象,生成一個完全一樣的拷貝(副本,內部屬性值一樣,而內存地址不一樣),但是這個拷貝和原對象不共用任何內部屬性元素,即實現了對象的深度克隆。這個“拷貝”的精確含義取決於該對象的類,一般含義是:

  1. 對任何的對象x,都有:x.clone()!=x。換言之,克隆對象與原對象不是同一個對象。
  2. 對任何的對象x,都有:x.clone().getClass() == x.getClass(),換言之,克隆對象與原對象的類型一樣。
  3. 如果對象x的equals()方法定義其恰當的話,那麽x.clone().equals(x)應當成立的。

二、原型模式的參與者及其角色

1、Prototype

  • 聲明一個克隆自身的接口。

2、ConcretePrototype

  • 實現一個克隆自身的操作。

3、Client

  • 讓一個原型克隆自身從而創建一個新的對象。

三、原型模式的類圖

技術分享圖片

四、原型模式的示例

  Java中可以使用以下幾種方式進行對象的深度克隆:

  1. 實現Cloneable接口,並重寫Object類中的clone()方法
  2. 實現序列化哈反序列化實現對象的深度克隆,實現Serializable接口或者Externalizable
    接口。

下面使用Cloneable進行說明:

1、Prototype

  使用Cloneable接口。

2、ConcretePrototype

  實現一個克隆自身的操作,這裏是clone()方法,需要重新進行定義。

 1 public class Name implements Cloneable{
 2     private String firstName;
 3     private String lastName;
 4     private Title title;
 5     //Constructor with no arguments
 6     public Name(){
7 8 } 9 //Constructor with all arguments 10 public Name(String firstName, String lastName, Title title) { 11 super(); 12 this.firstName = firstName; 13 this.lastName = lastName; 14 this.title = title; 15 } 16 //all getters and setters 17 public String getFirstName() { 18 return firstName; 19 } 20 public void setFirstName(String firstName) { 21 this.firstName = firstName; 22 } 23 public String getLastName() { 24 return lastName; 25 } 26 public void setLastName(String lastName) { 27 this.lastName = lastName; 28 } 29 30 public Title getTitle() { 31 return title; 32 } 33 public void setTitle(Title title) { 34 this.title = title; 35 } 36 @Override 37 public Name clone() throws CloneNotSupportedException { 38 Name nameClone = (Name)super.clone(); 39 nameClone.setFirstName(new String(this.getFirstName())); 40 nameClone.setLastName(new String(this.getLastName())); 41 nameClone.setTitle(this.getTitle().clone()); 42 return nameClone; 43 } 44 45 }

  這裏要註意的是,若屬性中有對象引用,同樣需要進行深度克隆,而該屬性也同樣需要實現Cloneable,重寫clone()方法。如上面的Title,如下:

 1 public class Title implements Cloneable{
 2     private String pre;
 3     private String title;
 4     //Constructor with no arguments
 5     public Title(){
 6         
 7     }
 8     //Constructor with all arguments
 9     public Title(String pre, String title) {
10         super();
11         this.pre = pre;
12         this.title = title;
13     }
14     public String getPre() {
15         return pre;
16     }
17     public void setPre(String pre) {
18         this.pre = pre;
19     }
20     public String getTitle() {
21         return title;
22     }
23     public void setTitle(String title) {
24         this.title = title;
25     }
26     @Override
27     public Title clone() throws CloneNotSupportedException {
28         Title title = (Title)super.clone();
29         title.setPre(new String(this.getPre()));
30         title.setTitle(new String(this.getTitle()));
31         return title;
32     }
33 }

3、Client

  創建原型對象,然後進行克隆。main方法中進行,輸出結果均為false。

 1 public class PrototypeTestApp {
 2     public static void main(String[] args) throws CloneNotSupportedException {
 3         Title title = new Title("Mr", "Doc");
 4         Name name = new Name("San", "Li", title);
 5         
 6         Name nameClone = name.clone();
 7         
 8         System.out.println(nameClone.getFirstName() == name.getFirstName());
 9         System.out.println(nameClone.getLastName() == name.getLastName());
10         System.out.println(nameClone.getTitle() == name.getTitle());
11         System.out.println(nameClone.getTitle().getPre() == name.getTitle().getPre());
12         System.out.println(nameClone.getTitle().getTitle() == name.getTitle().getTitle());
13     }
14 }

五、參考

1、參考《Head First設計模式》和GoF《設計模式:可復用面向對象軟件的基礎》

2、代碼可參考【github傳送門】、UML類圖參考【github傳送門

淺析設計模式(八)——創建型模式之Prototype(原型模式)