原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

public class Work implements Cloneable{
private String address;
private int time;
public void setAddress(String address) {
this.address = address;
}
public void setTime(int time) {
this.time = time;
}
@Override
public String toString() {
return "Work{" +
"address='" + address + '\'' +
", time=" + time +
'}';
}
@Override
protected Work clone() throws CloneNotSupportedException {
return (Work) super.clone();
}
}
public class Resume implements Cloneable{
private String name;
private int age;
private String company;
private Work work;
public Resume(String name){
this.name = name;
this.work = new Work();
}
private Resume (Work work) throws CloneNotSupportedException {
this.work = work.clone();
}
public void setAge(int age){
this.age = age;
}
public void setCompany(String company){
this.company = company;
}
public void setWork(String address, int time) {
work.setAddress(address);
work.setTime(time);
}
public void display(){
System.out.println(toString());
}
@Override
protected Resume clone() throws CloneNotSupportedException {
Resume resume = new Resume(this.work);
resume.name = this.name;
resume.age = this.age;
resume.company = this.company;
return resume;
}
@Override
public String toString() {
return "Resume{" +
"name='" + name + '\'' +
", age=" + age +
", company='" + company + '\'' +
", work=" + work +
'}';
}
}
浅拷贝
Java的object.clone()默认为浅拷贝,即对象的基本类型属性复制值,引用类型属性复制引用。
假如没有重写Resume对象的clone()方法
Resume resume = new Resume("周小狼");
Resume a = resume.clone();
两个对象的name、company、work引用会指向堆中的相同空间,当对象a对work操作会影响resume。
深拷贝
如上代码所示,重写Resume的clone方法,在方法中new一个resume对象,调用private构造器,传入当前对象的work属性,构造器再调用work的clone方法拷贝属性,此处要注意,如果work的属性中存在引用类型,还需要继续递归下去,才能实现两个resume对象的完全独立。(String类型是不可变,当修改String类型的值实际上是开辟新空间写入新值,将引用指向新空间,不会影响到其他对象)
测试
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Resume resume = new Resume("周小狼");
resume.setAge(15);
resume.setCompany("网鱼");
resume.setWork("同仁堂",2);
Resume a = resume.clone();
a.setCompany("林小媛");
a.setWork("长运堂",1);
resume.display();
a.display();
}
}
测试结果
Resume{name='周小狼', age=15, company='网鱼', work=Work{address='同仁堂', time=2}}
Resume{name='周小狼', age=15, company='林小媛', work=Work{address='长运堂', time=1}}
参考资料
《大话设计模式》
Java深拷贝和浅拷贝