天天看點

Java原型設計模式

原型模式

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

Java原型設計模式
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深拷貝和淺拷貝