2018-1-12 by Atlas
- 設計思想
通過給出一個原型對象來指明所要創建的對象的類型,然後用複製這個原型對象的方法創建出更多同類型的對象。原始模型模式允許動態的增加或減少產品類,產品類不需要非得有任何事先確定的等級結構,原始模型模式適用於任何的等級結構。缺點是每一個類都必須配備一個克隆方法。
- 應用場景
(1)種類過多無法整合成類時。
(2)不容易利用類產生對象實例時。
(3)希望把框架和所產生的對象實例分開時。
- UML 類圖
- Prototype(原型) 參與者
Prototype參與者規定複製(copy)對象實例再建立新對象實例的方法。- ConcretePrototype(具體原型)參與者
ConcretePrototype參與者是實際上實現先複製對象實例再建立新對象實例的方法。- Client(客戶)參與者
Client參與者利用複製對象實例的方法產生另一個新對象實例。- 原型模式的核心就是複製,表現到java語言就是實現Cloneable,實現clone方法,具體一點,就是clone操作時以原型爲模版,分配原型同樣大小的內存空間,然後創建一個跟原型一樣的對象實例。
- 簡單示例
public class Prototype implements Cloneable {
private int count;
private ShallowCopy shallowCopy;
private static Prototype prototype = new Prototype(0, new ShallowCopy());
private Prototype(int count, ShallowCopy shallowCopy){
this.count = count;
this.shallowCopy = shallowCopy;
}
public Prototype clone() throws CloneNotSupportedException {
Prototype prototype = (Prototype) super.clone();
// prototype.shallowCopy = this.shallowCopy.clone();
return prototype;
}
public static void main(String[] args) throws CloneNotSupportedException {
Prototype p0 = Prototype.prototype;
Prototype p1 = p0.clone();
System.out.println(p0 == p1);
System.out.println(p0.count == p1.count);
System.out.println(p0.shallowCopy == p1.shallowCopy);
}
}
class ShallowCopy implements Cloneable {
public ShallowCopy clone() throws CloneNotSupportedException {
return (ShallowCopy) super.clone();
}
}
- 成員count、shallowCopy的目的是說明clone操作的“淺拷貝”,不是原型模式的必要元素。
- 私有化Prototype目的是模擬不通過new語法創建對象實例,測試時儘量通過原型複製對象實例,不是原型模式的必要元素。
- System.out.println(p0 == p1);輸出false;說明clone後的對象實例是在內存中開闢的新空間。
- System.out.println(p0.count == p1.count);輸出true;其實對於基本數據類型來說,數值是存放在對象容器中的,既然對象實例是新開闢的內存空間,數值自然也是複製一份。
- System.out.println(p0.shallowCopy == p1.shallowCopy);輸出true;說明clone的原型對象實例中引用的對象的實例並沒有重新開闢內存進行復制,只是複製了對引用對象實例的引用,即“淺拷貝”。
- // prototype.shallowCopy = this.shallowCopy.clone();解開註釋後,System.out.println(p0.shallowCopy == p1.shallowCopy);輸出false;說明可以通過對clone對象實例中引用對象同樣執行clone來進行深一些層次的拷貝,但是如果對象實例的引用對象不對引用對象的引用對象顯式執行clone,無法達到傳遞拷貝,即完全深拷貝。
- 當然通過IO操作實現序列化、反序列化對象可以達到深拷貝的效果。
- 案例鑑賞
Spring中的原型模式。
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// ...
public static final String SCOPE_DEFAULT = "";
private String scope = SCOPE_DEFAULT;
public void setScope(String scope) {
this.scope = scope;
}
public String getScope() {
return this.scope;
}
/**
* Return whether this a <b>Singleton</b>, with a single shared instance
* returned from all calls.
* @see #SCOPE_SINGLETON
*/
public boolean isSingleton() {
return SCOPE_SINGLETON.equals(scope) || SCOPE_DEFAULT.equals(scope);
}
/**
* Return whether this a <b>Prototype</b>, with an independent instance
* returned for each call.
* @see #SCOPE_PROTOTYPE
*/
public boolean isPrototype() {
return SCOPE_PROTOTYPE.equals(scope);
}
/**
* Public declaration of Object's {@code clone()} method.
* Delegates to {@link #cloneBeanDefinition()}.
* @see Object#clone()
*/
public Object clone() {
return cloneBeanDefinition();
}
/**
* Clone this bean definition.
* To be implemented by concrete subclasses.
* @return the cloned bean definition object
*/
public abstract AbstractBeanDefinition cloneBeanDefinition();
// ...
}