Prototype Pattern
名稱由來
不是利用類來產生實例對象,而是從一個對象實例產生出另一個新的對象實例 ,根據被視為原型的對象實例 ,建立起的另一個新的對象實例就稱為原型模式(Ptototype Pattern)。
需求場景
- 種類過多無法整合成類時
第一種情形:若須處理的對象種類太多,如果要一個個設成不同的類,須產生大量的源程序文件
- 不容易利用類產生對象實例時
第二種情形:該對象的實例產生過程太復雜,很難利用類來建立。
- 希望把框架和所產生的對象實例分開時
第三種情形:希望讓產生對象實例時的框架不會只存在於某些特殊類時。
功能演示
測試程序類結構圖如下:
模式UML圖中,共有三個類:
- 接口,Product 己聲明抽象方法use 和 createClone的接口
- 管理類,Manager 利用createClone 復制對象實例的類
- 普通類,MessageBox 把字符串框起來use 的類,實現Product的createClone 和use 方法。
Product 接口
public interface Product extends Cloneable{
public abstract String use(String s);
public abstract Product createClone();
}
有了Product 接口 ,才可能進行復制。這個接口繼承java.lang.Cloneable 接口 ,利用clone 方法可自動對實現此接口 的類進行復制。
use 方法是“使用”的部分,“使用”代表何種意義則需看子類的實現。
createClone方法負責復制對象實例的部分。
Manager類
public class Manager {
private Hashtable<String, Product> showCase = new Hashtable<String, Product>();
public void register(String name, Product proto) {
showCase.put(name, proto);
}
public Product create(String protoName) {
Product p = showCase.get(protoName);
return p.createClone();
}
}
唯一跟其他類溝通的橋梁,負責添加和負責對象的實例。
MessageBox類
public class MessageBox implements Product {
private char decochar;
public MessageBox(char dechar) {
this.decochar = dechar;
}
@Override
public Product createClone() {
// TODO Auto-generated method stub
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
// TODO: handle exception
e.printStackTrace();
}
return p;
}
@Override
public String use(String s) {
// TODO Auto-generated method stub
int length = s.getBytes().length;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length + 4; i++) {
sb.append(decochar);
}
sb.append(decochar + "\n\"" + s + "\"\n" + decochar);
for (int i = 0; i < length + 4; i++) {
sb.append(decochar);
}
sb.append("");
return sb.toString();
}
}
createClone 方法是復制本身的方法,這裡所調用的clone 方法規定在java 語言規格內,它會產生另一個分身(本身的復制品)。在產生復制品時,若該字段包含對象實例,則其值也會跟著復制到新的對象實例。能利用clone 方法進行復制的只限於實現java.lang.Cloneable 接口 的類。如無實現則會報異常。但MessageBox 本身實現了Product ,而Product 是己經繼承了Cloneable接口。
Java 語言的clone 方法只能從本身的類(含子類)調用,所以如果是其他類的要求而進行復制時,則須另以其他方法(如createClone)把clone 抓起來。
android 界面入口測試該原型 Prototype 的PrototypeActivity
public class PrototypeActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.Button01))
.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Manager manager = new Manager();
MessageBox messageBox = new MessageBox('*');
manager.register("prototype", messageBox);
Product product = manager.create("prototype");
((EditText) findViewById(R.id.EditText01))
.setText(product.use("android ap Pattern"));
}
});
}
}
運行效果如下:
源碼下載:
原型模式