java設計模式之原型模式

原型模式概念

  該模式的思想就是將一個對象作爲原型,對其進行復制、克隆,產生一個和原對象類似的新對象。java中複製通過clone()實現的。clone中涉及深、淺複製。深、淺複製的概念如下:

  ⑴淺複製(淺克隆) 

      被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。換言之,淺複製僅僅複製所考慮的對象,而不復制它所引用的對象。 Object類提供的方法clone只是拷貝本對象,其對象內部的數組、引用對象等都不拷貝,還是指向原生對象的內部元素地址

  ⑵深複製(深克隆) 

      被複制對象的所有變量都含有與原來的對象相同的值,除去那些引用其他對象的變量。那些引用其他對象的變量將指向被複制過的新對象,而不再是原有的那些被引用的對象。換言之,深複製把要複製的對象所引用的對象都複製了一遍。 

package com.Geeksun.prototype;

import java.io.*;
import java.util.Date;

public class Girl implements Cloneable, Serializable {
    private static final long serialVersionUID = 1107125866318890906L;
    private String name;
    private Date birthday;
    private Address address;

    public Girl(String name, Date birthday,Address address) {
        this.name = name;
        this.birthday = birthday;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Girl{" +
                "name='" + name + '\'' +
                ", birthday=" + birthday +
                ", address=" + address +
                '}';
    }

    //淺複製
//    @Override
//    protected Object clone() throws CloneNotSupportedException {
//        return super.clone();
//    }

    //深複製1
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Girl girl = (Girl)super.clone();
        girl.setAddress((Address) address.clone());
        girl.setBirthday((Date)birthday.clone());
        return girl;
    }

    //深複製2
    public Object deepClone()throws IOException,ClassNotFoundException {
        /* 寫入當前對象的二進制流 */
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
}

class Address implements Cloneable,Serializable{

    public Address(){ }

    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
package com.Geeksun.prototype;

import java.util.Date;

public class Client {

    public static void main(String[] args) throws Exception {
        Address address = new Address();
        address.setAddress("HuBei");
        Girl girl = new Girl("Geeksun",new Date(),address);
        System.out.println(girl);
        Girl newGirl = (Girl) girl.deepClone();
        newGirl.getBirthday().setTime(1235);
        newGirl.getAddress().setAddress("BeiJing");
        System.out.println(girl);
        System.out.println(newGirl);
    }
}

最後得到的結果是

Girl{name='Geeksun', birthday=Thu Feb 21 17:41:44 CST 2019, address=Address{address='HuBei'}}
Girl{name='Geeksun', birthday=Thu Feb 21 17:41:44 CST 2019, address=Address{address='HuBei'}}
Girl{name='Geeksun', birthday=Thu Jan 01 08:00:01 CST 1970, address=Address{address='BeiJing'}}

   拷貝還有2個知識點,對象拷貝時,類的構造函數是不會被執行的。一個實現了 Cloneable 並重寫了 clone 方法的類 Programmer,有一個無參構造或有參構造 ,通過 new 關鍵字產生了一個對象 A,再然後通過 A.clone()方式產生了一個新的對象 T,那麼在對象拷貝時構造函數是不會被執行的。即拷貝的過程中只執行一次構造方法。

  Clone 與 final 兩對冤家。對象的 clone 與對象內的 final 屬性是由衝突.在上面的Programmer類中修改爲private final Address address;去掉get,set方法, proto.address=(Address) address.clone();這一句就會報錯: proto.address=(Address) address.clone();final類型不能重新設置值。解決辦法就是刪除掉fina咯

  深拷貝和淺拷貝建議不要混合使用,一個類中某些引用使用深拷貝某些引用使用淺拷貝,這是一種非常差的設計,特別是是在涉及到類的繼承,父類有幾個引用的情況就非常的複雜,建議深拷貝和淺拷貝分開實現。

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