04.26 設計模式之 Prototype(原型)

原型模式定義:

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

Prototype 模式允許一個對象再創建另外一個可定製的對象,根本無需知道任何如何創建的細節,工作原理是:通過將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝它們自己來實施創建。

淺複製:

當進淺複製時,clone函數返回的是一個引用,指向的是新的clone出來的對象,此對象與原對象分別佔用不同的堆空間。同時,複製出來的對象具有與原對象一致的狀態。此處對象一致的狀態是指:複製出的對象與原對象中的屬性值完全相等==。

下面以複製一本書為例:

1.定義Book類和Author類:

class Author {

private String name;

private int age;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

class Book implements Cloneable {

private String title;

private int pageNum;

private Author author;

public Book clone() {

Book book = null;

try {

book = (Book) super.clone();

} catch (CloneNotSupportedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return book;

}

public String getTitle() {

return title;

}

public void setTitle(String title) {

this.title = title;

}

public int getPageNum() {

return pageNum;

}

public void setPageNum(int pageNum) {

this.pageNum = pageNum;

}

public Author getAuthor() {

return author;

}

public void setAuthor(Author author) {

this.author = author;

}

}

由此我們發現:雖然複製出來的對象重新在堆上開闢了內存空間,但是,對象中各屬性確保持相等。對於基本數據類型很好理解,但對於引用數據類型來說,則意味著此引用類型的屬性所指向的對象本身是相同的, 並沒有重新開闢內存空間存儲。換句話說,引用類型的屬性所指向的對象並沒有複製。

由此,我們將其稱之為淺複製。當複製後的對象的引用類型的屬性所指向的對象也重新得以複製,此時,稱之為深複製。

二、深複製:

Java中的深複製一般是通過對象的序列化和反序列化得以實現。序列化時,需要實現Serializable接口。

下面還是以Book為例,看下深複製的一般實現過程:

1.定義Book類和Author類(注意:不僅Book類需要實現Serializable接口,Author同樣也需要實現Serializable接口!!):

class Author implements Serializable{

private String name;

private int age;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

class Book implements Serializable {

private String title;

private int pageNum;

private Author author;

public Book 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 (Book) ois.readObject();

}

public String getTitle() {

return title;

}

public void setTitle(String title) {

this.title = title;

}

public int getPageNum() {

return pageNum;

}

public void setPageNum(int pageNum) {

this.pageNum = pageNum;

}

public Author getAuthor() {

return author;

}

public void setAuthor(Author author) {

this.author = author;

}

}

從輸出結果中可以看出,深複製不僅在堆內存上開闢了空間以存儲複製出的對象,甚至連對象中的引用類型的屬性所指向的對象也得以複製,重新開闢了堆空間存儲。


分享到:


相關文章: