Gof 原文
Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.
使用背景
Prototype design pattern is used when the Object creation is a costly affair and requires a lot of time and resources and you have a similar object already existing.
原型模式的核心在于复制原型对象。当对象的构建过程比较耗时时,可以把当前系统中已存在的对象作为原型,对其进行复制(一般是基于二进制流的复制),躲避耗时的对象初始化过程,使得新对象的创建时间大大缩短,性能提升许多。
要求
原型设计模式要求要复制的对象必须提供复制特性。然而,使用对象属性的浅拷贝
还是深拷贝
取决于需求和设计决策。
import org.apache.commons.lang3.SerializationUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Employees implements Cloneable, Serializable {
private final 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<>();
for (String s : this.getEmpList()) {
temp.add(s);
}
return new Employees(temp);
}
public Object deepClone() {
try {
return SerializationUtils.clone(this);
} catch (Exception e) {
// 更详细的错误处理
System.err.println("Error cloning object: " + e.getMessage());
// 可以选择记录日志或者返回null
return null;
}
}
public Object deepClone2() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
Employees emps = new Employees();
emps.loadData();
Employees empsNew = (Employees) emps.deepClone();
List<String> list = empsNew.getEmpList();
list.add("John");
Employees empsNew1 = (Employees) emps.deepClone();
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]
原型模式在框架源码中的应用
我们找源码其实只需要看哪些接口实现了Cloneable即可。来看ArrayList类的实现。
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
原型模式在Spring源码中的应用
在Spring中,原型模式应用得非常广泛,例如scope="prototype"
、JSON.parseObject()
,都是原型模式的具体应用。
参考
digitalocean - Prototype Design Pattern