一句话概括:让类继承Cloneable接口
原型模式用于创建重复的对象,同时有能保证性能。属于创建型模式之一,它提供了一种创建对象的最佳方式。
当创建对象是一件昂贵的事情,需要大量的时间和资源,并且你有一个类似的对象已经存在时,就使用原型设计模式。
原型模式提供了一种机制,可以将原始对象复制到新对象,然后根据我们的需要对新对象进行修改。 原型设计模式使用java克隆的方法来复制对象。
Prototype Design Pattern Example
举个例子来更好的理解原型模式。假设我们有一个从数据库加载数据的对象。现在我们需要多次在我们的程序中修改这些数据,不希望在原来的数据对象上直接操作,但是这时使用new关键字创建新的对象并从数据库中再次加载所有的数据也并不是合适。
一个比较好的方法是将现有对象克隆到新对象中,然后执行数据操作。
原型模式要求正在复制的对象应提供复制功能(拷贝对象不应该由其他任何Class来完成)。 具体使用对象属性的浅拷贝还是深拷贝取决于需求及其设计决策。
示例代码:
//继承Cloneable接口
public class Employees implements Cloneable{
private List empList;
public Employees(){
empList = new ArrayList();
}
public Employees(List 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 getEmpList() {
return empList;
}
//拷贝对象
@Override
public Object clone() throws CloneNotSupportedException{
//这里是深拷贝
List temp = new ArrayList();
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 list = empsNew.getEmpList();
list.add("John");
List 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]
如果没有提供对象克隆,我们将不得不每次都进行数据库调用以获取员工列表,导致资源和时间消耗。
这种模式使用很常见,比如写Web应用的时候,把数据库里的相对不太容易更改的数据写到缓存对象中,每次请求的时候将该对象复制给请求响应的方法。然后用一个定时器定期更新该缓存对象。确保请求响应方法不会破坏数据内容。而且不用每次请求都访问一次数据库。