1.定義
原型模式屬於一種創建型模式,與其他創建型模式不同,原型模式不是直接構造對象,而是通過複製一個已經存在的實例返回新的實例。
2.適用性
爲何要拷貝而不直接生成?有些時候直接構造實例花費比較大,比如在構造對象的時候需要做大量的數據庫查詢,這樣如果構造許多類似的對象還重複地查詢數據庫則開銷很大,很沒效率。此外,此類型的實例屬性都相同。這樣直接拷貝現有的實例,在需要情況下做一些小的修改會顯得高效許多。
3.結構
- Prototype: 聲明一個克隆自身的接口
- ConcretePrototype:實現一個克隆自身的操作
- Client : 讓一個原型克隆自身從而創建一個新的對象
從上圖我們可以看出,原型模式中無論Prototype還是ConcretePrototype都提供有一個Clone()方法,方便拷貝自身返回新的實例。而Client類中註冊有一個Prototype對象,方便Client從prototype克隆對象。
4.舉例說明
Cookie定義了一個抽象的Prototype,ChocolateCookie和MilkCookie分別是ConcretePrototype,CookieManager是Client,ManageCookies是測試類。
Cookie.java:
package com.andy.designpattern.prototype;
public class Cookie implements Cloneable {
protected String name;
public Cookie() {
// TODO Auto-generated constructor stub
name = "Cookie";
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (Cookie)super.clone();
}
public String getName() {
return name;
}
}
ChocolateCookie.java:
package com.andy.designpattern.prototype;
public class ChocolateCookie extends Cookie {
public ChocolateCookie() {
// TODO Auto-generated constructor stub
this.name = "ChocolateCookie";
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (ChocolateCookie)super.clone();
}
}
MilkCookie.java:
package com.andy.designpattern.prototype;
import java.util.jar.Attributes.Name;
public class MilkCookie extends Cookie {
public MilkCookie(){
this.name = "MilkCookie";
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (MilkCookie)super.clone();
}
}
CookieMachine.java:
package com.andy.designpattern.prototype;
public class CookieMachine {
private Cookie cookie;
public Cookie makeCookie(Cookie cookie) throws CloneNotSupportedException{
return (Cookie)cookie.clone();
}
}
ManageCookies.java:
package com.andy.designpattern.prototype;
public class ManageCookies {
public static void main(String[] args) {
CookieMachine machine = new CookieMachine();
try {
System.out.println(machine.makeCookie(new MilkCookie()).getName());
System.out.println(machine.makeCookie(new ChocolateCookie()).getName());
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
5.效果
Prototype與Abstract Factory和Builder一樣,對用戶隱藏了產品類,減少了客戶知道的名字的數目。
優點:
- 可以再運行時刻增加和刪除產品,這一點使原型模式比其他的創建型模式更加靈活
- 減少子類的構造,有些時候可以節省不少資源
- 用類動態配置應用,一些運行時刻環境允許你動態將類裝在到應用中
缺點:
每一個Prototype子類都必須實現Clone操作,有時候會有些困難。比如,當所考慮的類已經存在時就難以增加Clone操作;當內部包括一些不支持拷貝或者有循環引用的對象時,實現克隆可能也會很困難。