一句話概括:讓類繼承Cloneable接口
原型模式用于創(chuàng)建重復的對象恰起,同時有能保證性能裹粤。屬于創(chuàng)建型模式之一束亏,它提供了一種創(chuàng)建對象的最佳方式。
當創(chuàng)建對象是一件昂貴的事情叔磷,需要大量的時間和資源拢驾,并且你有一個類似的對象已經(jīng)存在時,就使用原型設計模式改基。
原型模式提供了一種機制繁疤,可以將原始對象復制到新對象,然后根據(jù)我們的需要對新對象進行修改。 原型設計模式使用java克隆的方法來復制對象稠腊。
Prototype Design Pattern Example
舉個例子來更好的理解原型模式躁染。假設我們有一個從數(shù)據(jù)庫加載數(shù)據(jù)的對象。現(xiàn)在我們需要多次在我們的程序中修改這些數(shù)據(jù)架忌,不希望在原來的數(shù)據(jù)對象上直接操作吞彤,但是這時使用new關(guān)鍵字創(chuàng)建新的對象并從數(shù)據(jù)庫中再次加載所有的數(shù)據(jù)也并不是合適。
一個比較好的方法是將現(xiàn)有對象克隆到新對象中叹放,然后執(zhí)行數(shù)據(jù)操作饰恕。
原型模式要求正在復制的對象應提供復制功能(拷貝對象不應該由其他任何Class來完成)。 具體使用對象屬性的淺拷貝還是深拷貝取決于需求及其設計決策井仰。
示例代碼:
//繼承Cloneable接口
public class Employees implements Cloneable{
private List<String> empList;
public Employees(){
empList = new ArrayList<String>();
}
public Employees(List<String> list){
this.empList=list;
}
public void loadData(){
//read all employees from database and put into the list
empList.add("Pankaj");
empList.add("Raj");
empList.add("David");
empList.add("Lisa");
}
public List<String> getEmpList() {
return empList;
}
//拷貝對象
@Override
public Object clone() throws CloneNotSupportedException{
//這里是深拷貝
List<String> temp = new ArrayList<String>();
for(String s : this.getEmpList()){
temp.add(s);
}
return new Employees(temp);
}
}
寫個測試代碼來證明原型模式的好處:
public class PrototypePatternTest {
public static void main(String[] args) throws CloneNotSupportedException {
Employees emps = new Employees();
emps.loadData();
//Use the clone method to get the Employee object
Employees empsNew = (Employees) emps.clone();
Employees empsNew1 = (Employees) emps.clone();
List<String> list = empsNew.getEmpList();
list.add("John");
List<String> list1 = empsNew1.getEmpList();
list1.remove("Pankaj");
System.out.println("emps List: "+emps.getEmpList());
System.out.println("empsNew List: "+list);
System.out.println("empsNew1 List: "+list1);
}
}
上述代碼的輸出是:
emps List: [Pankaj, Raj, David, Lisa]
empsNew List: [Pankaj, Raj, David, Lisa, John]
empsNew1 List: [Raj, David, Lisa]
如果沒有提供對象克隆埋嵌,我們將不得不每次都進行數(shù)據(jù)庫調(diào)用以獲取員工列表,導致資源和時間消耗。
這種模式使用很常見糕档,比如寫Web應用的時候莉恼,把數(shù)據(jù)庫里的相對不太容易更改的數(shù)據(jù)寫到緩存對象中,每次請求的時候?qū)⒃搶ο髲椭平o請求響應的方法速那。然后用一個定時器定期更新該緩存對象俐银。確保請求響應方法不會破壞數(shù)據(jù)內(nèi)容。而且不用每次請求都訪問一次數(shù)據(jù)庫端仰。