在本節中,我們將學習和使用原型模式;這一節學習的原型模式也是創建型
模式的其中之一。再次複習一下:創建型
模式就是描述如何去更好的創建一個對象。
我們都知道,在JAVA 語言中。使用new
關鍵字創建一個新對象。將新的對象放到堆內存
裏面。當然,這個內存肯定是有大小限制的,況且,JAVA 不同於C語言等。 有內存管理機制,就是我們常說的垃圾回收器GC
,才可以保證內存不被溢出。
說這些其實就是為了表示:為啥要用單例模式,能節省內存的時候,能用一個對象解決重複的事情,絕對不會創建多個。
概述
原型模式描述的如何快速創建重複的對象,並且減少new 關鍵字的使用。
- 抽象原型類
- 具體原型類
- 訪問類
容我來一個一個解釋:
抽象原型類 也就是我們具體要實現的某個類,這個類在JAVA 裏面是有具體的接口的,其實是一個空接口,Cloneable
* @author unascribed
* @see java.lang.CloneNotSupportedException
* @see java.lang.Object#clone()
* @since JDK1.0
*/
public interface Cloneable {
}
我們會發現,這個類沒有任何的方法,怎麼來實現它,不要慌。先接着走。
具體原型類 也就是我們具體要克隆
的對象。比如我們重複的要創建100個學生Student
對象,那麼具體的學生對象就是具體原型類
public class Student implements Cloneable {
private int id;
private String name;
private int sex;
}
訪問類 我就不必多說了
淺克隆和深克隆
原型模式其實也分淺克隆和深克隆。如何理解這兩個概念呢?
淺克隆
protected native Object clone() throws CloneNotSupportedException;
淺克隆,只需要具體原型類
實現Cloneable 接口,並且重寫父類Object
類的clone() 方法,即可實現對象的淺克隆。
Student student1 = new Student(1, "李四");
Student student2 = student1.clone();
System.out.println(student1);
System.out.println(student2);
System.out.println(student1 == student2);
---------------------
學號:1,姓名:李四
學號:1,姓名:李四
false
- 通過執行
clone()
方法即可創建一個相同的,具有同樣屬性的對象。 - 並且是新的對象,內存地址有所不同。
我們來看看,對於引用類型的變量,淺克隆是否可以進行克隆;
Teacher teacher = new Teacher(1, "張老師");
Student student1 = new Student(1, "李四", teacher);
Student student2 = student1.clone();
System.out.println(student1);
System.out.println(student2);
System.out.println(student1 == student2);
------------
學號:1,姓名:李四,老師=Teacher@1b6d3586
學號:1,姓名:李四,老師=Teacher@1b6d3586
false
我們發現,引用類型並沒有被克隆,也就是說:
特點
- 淺克隆對於基本類型,可以進行完全的克隆,並且克隆的對象是一個新的對象
- 但是對象裏面的引用,是無法被克隆的。
深克隆(序列化)
何謂序列化?
我們創建的都是保存在內存裏面的,只要被虛擬機GC進行回收,那麼這個對象的任何屬性都是消失,我們能不能找一個方法,將內存中這種對象的屬性以及對象的狀態通過某種東西保存下來,比如保存到數據庫,下次從數據庫將這個對象還原
到內存裏面。 這就是序列化。
- 序列化
內存對象->序列字符
- 反序列化
序列字符->內存對象
請參考: https://baike.baidu.com/item/序列化/2890184
JAVA 序列化
* @see java.io.Externalizable
* @since JDK1.1
*/
public interface Serializable {
}
JAVA 提供了一個空接口,其實這個接口和上面的Cloneable
一樣,都是一個空接口,其實這個空接口就是作為一種標識
你的對象實現了這個接口,JAVA 認為你的這個就可以被序列化 ,就是這麼簡單。
Teacher teacher = new Teacher(1, "張老師");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(outputStream);
stream.writeObject(teacher);
System.out.println(Arrays.toString(outputStream.toByteArray()));
----------
[-84, -19, 0, 5, 115, 114, 0, 7, 84, 101, 97,。。。。。。
通過將對象序列化、其實也就是將內存中的對象轉化為二進制 字節數組
反序列化
Teacher teacher = new Teacher(1, "張老師");
System.out.println(teacher);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(outputStream);
stream.writeObject(teacher);
System.out.println(Arrays.toString(outputStream.toByteArray()));
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream);
Teacher teacher1 = (Teacher) inputStream.readObject();
System.out.println(teacher1);
---------------
id=1,name=張老師
[-84, -19, 0, 5, 115, xxxxx,-127, -27, -72, -120]
id=1,name=張老師
通過序列化和反序列化,即可對象的深克隆
小結
這一節,在講述 原型模式的同時,將原有實現原型模式的clone()
淺克隆,延伸到深克隆這一概念。其實JAVA 的原型模式,實現起來較為簡單。但還是要按需要實現,Object 類提供的 clone 淺克隆
是沒辦法克隆對象的引用類型的。需要克隆引用類型,還是需要序列化
深克隆
參考
http://c.biancheng.net/view/1343.html
https://www.liaoxuefeng.com/wiki/1252599548343744/1298366845681698
代碼示例
https://gitee.com/mrc1999/Dev-Examples
歡迎關注
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※新北清潔公司,居家、辦公、裝潢細清專業服務
※別再煩惱如何寫文案,掌握八大原則!
※教你寫出一流的銷售文案?
※超省錢租車方案
※FB行銷專家,教你從零開始的技巧