1. 程式人生 > >java常用設計模式二:原型模式

java常用設計模式二:原型模式

在說原型模式之前先說一下淺拷貝深拷貝的概念

一、淺拷貝和深拷貝

1、淺拷貝   

在java中,物件建立後需要有一個引用變數來指向該物件實際的地址空間,也就是說引用變數與物件實體是兩個不同的資料體。在Object類的clone()方法中,對物件欄位進行復制時,如果欄位是基本資料型別(如int、double等),則會複製欄位的值到一個新的變數中,而欄位是引用型別(String除外),則僅會將引用值複製給新物件中的相應欄位中,也就是說,兩個欄位指向了同一個物件例項。看以下的例子來理解淺拷貝。
1)使用者類

public class User{
    private
String name; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }

2)學生類:如果要讓Student類支援clone方法,必須實現Cloneable介面

public class Student implements Cloneable {
    private User user;
    private String message;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getMessage() {
        return message;
    }

    public
void setMessage(String message) { this.message = message; } /** * 重寫clone()方法為public型別,並呼叫Object的本地clone()方法,實現淺拷貝功能 */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }

3)測試類

public class TestCopy {
    public static void main(String[] args) throws CloneNotSupportedException {
        User user = new User();
        user.setName("張三");
        user.setSex("");
        Student oldStudent = new Student();
        oldStudent.setUser(user);
        oldStudent.setMessage("old message");

        System.out.println("oldStudent:"+oldStudent.getUser().getName()+" :"+oldStudent.getUser().getSex()+" :"+oldStudent.getMessage());
        Student copyStudent = (Student) oldStudent.clone();
        System.out.println("copyStudent:"+copyStudent.getUser().getName()+" :"+copyStudent.getUser().getSex()+" :"+copyStudent.getMessage());
        System.out.println("oldStudent == copyStudent ? " +(oldStudent == copyStudent));

        copyStudent.getUser().setName("李麗");
        copyStudent.getUser().setSex("女");
        copyStudent.setMessage("new message");
        System.out.println("修改copyStudent的內容後===========");
        System.out.println("oldStudent:"+oldStudent.getUser().getName()+" :"+oldStudent.getUser().getSex()+" :"+oldStudent.getMessage());
        System.out.println("copyStudent:"+copyStudent.getUser().getName()+" :"+copyStudent.getUser().getSex()+" :"+copyStudent.getMessage());

    }
}
oldStudent:張三 :男 :old message
copyStudent:張三 :男 :old message
oldStudent == copyStudent ? false
修改copyStudent的內容後===========
oldStudent:李麗 :女 :old message
copyStudent:李麗 :女 :new message

由以上結果可知道,oldStudent和copyStudent並不是同一個物件,當將copyStudent的user資訊和message資訊修改後,oldStudent的user資訊相應也改變了,oldStudent的message沒有改變。

得出結論:在進行用Object類對Student的User屬性進行拷貝時是淺拷貝,也就是說只是將oldStudent裡面user引用變數複製到了copyStudent裡面,2個變數實際上指向的是同一塊地址。

 

 2、深拷貝   

那就是對於引用型變數,深拷貝會開闢一塊新的記憶體空間,將被複制引用所指向的物件例項的各個屬性複製到新的記憶體空間中,然後將新的引用指向塊記憶體(也就是一個新的例項)。以後對新引用指向的例項屬性進行修改的時候就不會影響到老引用指向的例項屬性。