原始模型模式屬於對象的創建模式。通過一個原型對象來指明要創建對象的類型,然後用復制原型對象的方法來創建出更多同類型的對象。
Java所有的類都是從java.lang.Object類繼承來的,Object類提供clone()方法對對象進行復制。一般調用clone()方法需要滿足一下條件:
1、對於任何對象x,都有:x.clone()!=x。也就是克隆的對象和原對象不是一個對象。
2、對於任何對象x,都有:x.clone().getClass()=x.getClass()。也就是克隆對象與原對象是相同的類型。
3、如果對象x的equal()方法定義恰當的話,那麼x.clone().equal(x)應該成立。
原始模型模式分為兩種類型:1、簡單形式;2、登記形式。下面分別解釋下這兩種類型。
簡單形式的原始模型模式類圖:
這種模式的三個角色:
1、客戶角色:客戶提出創建對象的請求。
2、抽象原型:抽象角色,給出具體原型所需的接口。
3、具體原型:被復制的對象,需實現抽象原型所需要的接口。
抽象原型代碼:
public interface Prototype extends Cloneable{ public Object clone() throws CloneNotSupportedException; }
具體原型代碼:
public class ConcrecePrototype implements Prototype{ public Object clone() throws CloneNotSupportedException { try { return super.clone(); } catch (Exception e) { return null; } } }
客戶角色代碼:
public class Client { private Prototype prototype; public void operation(Prototype example) throws CloneNotSupportedException{ Prototype p = (Prototype) example.clone(); } }
登記形式的原始模型模型類圖:
這種模式的角色:
1、客戶角色:客戶提出創建對象的請求。
2、抽象原型:抽象角色,給出具體原型所需的接口。
3、具體原型:被復制的對象,需實現抽象原型所需要的接口。
4、原型管理器:創建具體原型類對象,並記錄每一個被創建的對象。
抽象原型代碼:
public interface Prototype extends Cloneable{ public Object clone() throws CloneNotSupportedException; }
具體原型代碼:
public class ConcrecePrototype implements Prototype{ public synchronized Object clone() throws CloneNotSupportedException { Prototype temp = null; try { temp = (Prototype) super.clone(); } catch (Exception e) { System.out.println("clone fail"); }finally{ return temp; } } }
原型管理器代碼:
public class PrototypeManager { private Vector vector = new Vector(); public void add(Prototype e){ vector.add(e); } public Prototype get(int i){ return (Prototype) vector.get(i); } }
客戶端代碼:
public class Client { private PrototypeManager pm; private Prototype p; public void registerPrototype(Prototype prototype) throws CloneNotSupportedException{ Prototype temp = (Prototype) prototype.clone(); pm.add(temp); } }
可以看出,如果要創建的原型對象少且固定的話可以考慮使用簡單形式的原型模式。如果要創建的原型對象不固定,可以使用登記形式的原型模式。原型對象有原型管理器保管,如果其中有則直接拿出,沒有則復制並加入其中。
看到這裡就會想到了java中重要的話題:淺復制和深復制。
淺復制:被復制對象的所有變量都與原來對象有相同的值,而所有對其對象的引用都指向原對象。淺復制只考慮復制所考慮的對象,而不復制它所引用的對象。
深復制:被復制對象的所有變量都與原來對象有相同的值,那些引用其他對象的變量指向被復制的新對象。深復制中那些引用其他對象的變量將指向被復制過的新對象,也就是深復制把要復制的對象所引用的對象都復制了一遍。
優點:
1、 原始模型模型模式允許動態地增加或減少產品類。由於創建產品類實例的方法是產品類內部具有的,因此,增加新產品的對整個結構沒有影響。
2、 原始模型模式提供簡化的創建結構。工廠方法模式常常需要有一個與產品類等級相同的結構,而原始模型模式就不需要這樣。
3、 具有給一個應用軟件動態加載新功能的能力。
4、 產品類不需要非得有任何事先確定的等級結構,因為原始模型模式適用於任何的等級。
缺點:
原始模型模式最主要的缺點就是需要為每一個類都必須具備一個復制方法。
另外,如果在原型對象中有間接對象,可以將間接對象設置為transient不予以復制,或者自行創建出相當的同種對象。