在本節中,咱們將學習和使用原型模式;這一節學習的原型模式也是建立型
模式的其中之一。再次複習一下:建立型
模式就是描述如何去更好的建立一個對象。html
咱們都知道,在JAVA 語言中。使用new
關鍵字建立一個新對象。將新的對象放到堆內存
裏面。固然,這個內存確定是有大小限制的,何況,JAVA 不一樣於C語言等。 有內存管理機制,就是咱們常說的垃圾回收器GC
,才能夠保證內存不被溢出。java
說這些其實就是爲了表示:爲啥要用單例模式,能節省內存的時候,能用一個對象解決重複的事情,絕對不會建立多個。git
原型模式描述的如何快速建立重複的對象,而且減小new 關鍵字的使用。數據庫
容我來一個一個解釋:數組
抽象原型類 也就是咱們具體要實現的某個類,這個類在JAVA 裏面是有具體的接口的,實際上是一個空接口,Cloneable
學習
* @author unascribed * @see java.lang.CloneNotSupportedException * @see java.lang.Object#clone() * @since JDK1.0 */ public interface Cloneable { }
咱們會發現,這個類沒有任何的方法,怎麼來實現它,不要慌。先接着走。.net
具體原型類 也就是咱們具體要克隆
的對象。好比咱們重複的要建立100個學生Student
對象,那麼具體的學生對象就是具體原型類
code
public class Student implements Cloneable { private int id; private String name; private int sex; }
訪問類 我就沒必要多說了htm
原型模式其實也分淺克隆和深克隆。如何理解這兩個概念呢?對象
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進行回收,那麼這個對象的任何屬性都是消失,咱們能不能找一個方法,將內存中這種對象的屬性以及對象的狀態經過某種東西保存下來,好比保存到數據庫,下次從數據庫將這個對象還原
到內存裏面。 這就是序列化。
內存對象->序列字符
序列字符->內存對象
* @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