原型模式
用原型執行個體指定建立對象的種類,并且通過拷貝這些原型建立新的對象。

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深拷貝和淺拷貝