定义
原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原理
将一个原型对象传给那个要发动创建的对象,这个对象通过请求原型对象拷贝它们自己来实施创建。克隆对象和原对象具有相同的属性和状态。
类图
优点
- 当创建类的新实例时的代价更大时,使用原型模式复制一个已有的实例可以提高创建新实例的效率。
- 可以动态的保存当前对象的状态。在运行时可以随时使用对象流保存当前对象的一个复制品。
- 可以在运行时创建新的对象,而无需创建一系列类和继承结构。
- 可以动态的添加、删除原型的复制品。
缺点
每个类必须配备一个克隆方法,不容易对已有的类进行改造。
适用
- 系统应该独立于产品创建、构成、表示时。
- 实例化的类在运行时指定。
- 避免创建一个与产品类层次平行的工厂类层次时。
- 当一个类的实例只能有几个不同状态组合中的一种时。
深拷贝和浅拷贝
浅拷贝是只拷贝引用(引用类型),源对象指向同一个,改变克隆对象的值时,原对象也变了。深拷贝值和引用都拷贝,改变克隆对象并不会影响原对象。但对于值类型(基本类型)来说,浅拷贝和深拷贝没有区别,原对象和克隆对象互不影响。
public class WorkExperience implements Serializable {
private static final long serialVersionUID = 1L;
private String workDate;
private String workCompany;
public String getWorkDate() {
return workDate;
}
public WorkExperience setWorkDate(String workDate) {
this.workDate = workDate;
return this;
}
public String getWorkCompany() {
return workCompany;
}
public WorkExperience setWorkCompany(String workCompany) {
this.workCompany = workCompany;
return this;
}
public class Resume implements Cloneable, Serializable{
private static final long serialVersionUID = -4410449301166191440L;
private String name;
private String gender;
private int age;
// 引用“工作经历”对象,为演示深度拷贝和浅度拷贝而用
private WorkExperience workExperience;
public Resume() {
// 在“简历”类实例化时,同时实例化“工作经历”类
workExperience = new WorkExperience();
}
public void display() {
System.out.println(this.getName() + " " + this.getGender() + " "
+ this.getAge() + "\n工作经历: "
+ this.getWorkExperience().getWorkDate() + " "
+ this.getWorkExperience().getWorkCompany());
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// 通过对象序列化,实现深度拷贝
public Object deepClone() throws IOException, ClassNotFoundException {
// 将对象写入流内
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 从流内读出对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
bos.toByteArray()));
return ois.readObject();
}
public String getName() {
return name;
}
public Resume setName(String name) {
this.name = name;
return this;
}
public String getGender() {
return gender;
}
public Resume setGender(String gender) {
this.gender = gender;
return this;
}
public int getAge() {
return age;
}
public Resume setAge(int age) {
this.age = age;
return this;
}
public WorkExperience getWorkExperience() {
return workExperience;
}
public void setWorkExperience(String workDate, String workCompany) {
workExperience.setWorkDate(workDate);
workExperience.setWorkCompany(workCompany);
}
}
public class PrototypeClient {
public static void shallowCopy() throws CloneNotSupportedException {
Resume aResume = new Resume();
aResume.setName("大鸟 ").setGender("男 ").setAge(25);
aResume.setWorkExperience("1999-2002, ", "XX公司");
Resume bResume = (Resume) aResume.clone();
bResume.setWorkExperience("1999-2002, ", "YY公司");
Resume cResume = (Resume) aResume.clone();
cResume.setWorkExperience("1999-2002, ", "ZZ公司");
System.out.println(">>>>>>浅度拷贝:");
aResume.display();
bResume.display();
cResume.display();
}
public static void deepCopy() throws CloneNotSupportedException,
ClassNotFoundException, IOException {
Resume aResume = new Resume();
aResume.setName("大鸟 ").setGender("男 ").setAge(25);
aResume.setWorkExperience("1999-2002, ", "XX公司");
Resume bResume = (Resume) aResume.deepClone();
bResume.setWorkExperience("1999-2002, ", "YY公司");
Resume cResume = (Resume) aResume.deepClone();
cResume.setWorkExperience("1999-2002, ", "ZZ公司");
System.out.println(">>>>>>深度拷贝:");
aResume.display();
bResume.display();
cResume.display();
}
public static void main(String[] args) throws CloneNotSupportedException,
ClassNotFoundException, IOException {
// 浅度拷贝
shallowCopy();
System.out.println("==================================");
// 深度拷贝
deepCopy();
}
}