設計模式 – 原型模式(Prototype)

ü  原型模式:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象

ü  JAVA中可以通過實現Cloneable或者繼承Cloneable類來實現對象的拷貝,然後就

可以調用clone()方法進行對象的複製了(直接調用會報CloneNotSupported

Exception)。但是此處需要注意的是clone()方法是由java.lang.Object類定義的,Object類是JAVA類層次的基類,因此所有類都會繼承clone()方法,而不要誤以爲是Cloneabel接口(Cloneable)中有定義clone()方法;

ü  還需要注意的是clone()方法做的是淺拷貝,所做的操作是直接賦值字段的內容,即這個操作並不管字段對應的對象實例內容。假設現在有個字段對應到一個數組,當使用clone()方法進行復制時,複製的結果只對應到該數組的參照而已,並不會一個個複製該數組的元素。如果只做淺拷貝clone無法滿足你的要求,設計類的程序員也可以重寫clone()方法,自行定義想要的複製結果

ü  還需要注意的是:clone只會進行復制而已,並沒有調用構造函數,如果該類在產生對象實例時需要做特殊的初始化,則應將處理操作語句放在clone方法之內;

實例:簡歷複製

Ø  文件:Resume.java

package com.yilong.prototype;

public class Resume implements Cloneable {

    private String name;

    private String sex;

    private int age;

    private String timearea;

    private String company;

    public Resume(String name) {

       this.name = name;

    }

    public void setPersonalInfo(String sex, int age) {

       this.sex = sex;

       this.age = age;

    }

    public void setWrokExperience(String timearea, String company) {

       this.timearea = timearea;

       this.company = company;

    }

    public Resume resumeClone() {

       Resume resume = null;

       try {

           resume = (Resume)clone();

       } catch (CloneNotSupportedException e) {

           e.printStackTrace();

       }

        return resume;

    }

    public void display() {

       System.out.println("---------------------------------");

       System.out.println("姓名:" + this.name);

       System.out.println("性別:" + this.sex + " 年齡:" + this.age);

       System.out.println("工作經歷:" + this.timearea + " " + this.company);

       System.out.println("---------------------------------");

    }

}

Ø  測試文件Main.java

package com.yilong.prototype;

public class Main {

    public static void main(String[] args) {

       Resume resume1 = new Resume("逸龍");

       resume1.setPersonalInfo("", 22);

       resume1.setWrokExperience("2001-2004", "XX公司");

       Resume resume2 = resume1.resumeClone();

       resume2.setPersonalInfo("", 23);

       resume2.setWrokExperience("2001-2005", "XXX公司");

       resume1.display();

       resume2.display();

    }

}

打印結果:

---------------------------------

姓名:逸龍

性別:男 年齡:22

工作經歷:2001-2004 XX公司

---------------------------------

---------------------------------

姓名:逸龍

性別:男 年齡:23

工作經歷:2001-2005 XXX公司

---------------------------------

ü  淺複製:被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用都仍然指向原來的對象;當我們需要把複製的對象所引用的對象都複製一遍的時候,就需要用到深複製:把引用對象的變量指向複製過的新對象,而不是原來的被引用的對象;下面是淺複製可能帶來的不滿足需求的情況:

但結果顯示爲:

實例:將上述的工作經歷單獨設置爲一個類

Ø  文件WorkInfo.java

package com.yilong.prototype;

public class WorkInfo {

    private String timeArea;

    private String company;

   

    public String getCompany() {

       return company;

    }

    public void setCompany(String company) {

       this.company = company;

    }

    public String getTimeArea() {

       return timeArea;

    }

    public void setTimeArea(String timeArea) {

       this.timeArea = timeArea;

    }

}

Ø  文件Resume.java

package com.yilong.prototype;

public class Resume implements Cloneable {

    private String name;

    private String sex;

    private int age;

    private WorkInfo workInfo;

    public Resume(String name) {

       this.name = name;

    }

    public void setPersonalInfo(String sex, int age) {

       this.sex = sex;

       this.age = age;

    }

    public Resume resumeClone() {

       Resume resume = null;

       try {

           resume = (Resume)clone();

       } catch (CloneNotSupportedException e) {

           e.printStackTrace();

       }

       return resume;

    }

    public void display() {

       System.out.println("---------------------------------");

       System.out.println("姓名:" + this.name);

       System.out.println("性別:" + this.sex + " 年齡:" + this.age);

       System.out.println("工作經歷:" + this.workInfo.getTimeArea() + " " + this.workInfo.getCompany());

       System.out.println("---------------------------------");

    }

    public WorkInfo getWorkInfo() {

       return workInfo;

    }

    public void setWorkInfo(WorkInfo workInfo) {

       this.workInfo = workInfo;

    }

}

Ø  測試文件Main.java

package com.yilong.prototype;

public class Main {

    public static void main(String[] args) {

       Resume resume1 = new Resume("逸龍");

       resume1.setPersonalInfo("", 22);

       WorkInfo workInfo = new WorkInfo();

       workInfo.setTimeArea("2001-2003");

       workInfo.setCompany("XX公司");

       resume1.setWorkInfo(workInfo);

       Resume resume2 = resume1.resumeClone();

       resume2.setPersonalInfo("", 23);

       resume2.getWorkInfo().setTimeArea("2003-2004");

       resume2.getWorkInfo().setCompany("XXVV公司");

       resume1.display();

       resume2.display();

    }

}

打印結果:

---------------------------------

姓名:逸龍

性別:男 年齡:22

工作經歷:2003-2004 XXVV公司

---------------------------------

---------------------------------

姓名:逸龍

性別:男 年齡:23

工作經歷:2003-2004 XXVV公司

---------------------------------

結果說明:可見,打印的結果都是最後一次設置的工作經歷的值,這主要是因爲copy的是工作經歷對象的引用,也就是說resume1resume2裏的workInfo都是指向同一個WorkInfo對象,而要達到預期的目標,主要是瞭解其中的原理,即在修改WorkInfo對象的值前必須新new一個新的WorkInfo對象,然後將其值設置爲原來的WorkInfo裏的值,這樣再修改就會修改新分配的那塊WorkInfo內存的值,具體可以將文件Resume.java裏的resumeClone()函數修改爲:

public Resume resumeClone() {

       Resume resume = null;

       try {

           resume = (Resume)clone();

           WorkInfo workInfo = new WorkInfo();

           workInfo.setTimeArea(this.getWorkInfo().getTimeArea());

           workInfo.setCompany(this.getWorkInfo().getCompany());

           resume.setWorkInfo(workInfo);

       } catch (CloneNotSupportedException e) {

           e.printStackTrace();

       }

       return resume;

}

打印結果:

---------------------------------

姓名:逸龍

性別:男 年齡:22

工作經歷:2001-2003 XX公司

---------------------------------

---------------------------------

姓名:逸龍

性別:男 年齡:23

工作經歷:2003-2004 XXVV公司

---------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章