創建型模式————原型模式(2.3)
- 2019 年 10 月 6 日
- 筆記
什麼是原型模式?
簡單來說,通過複製的方式創建對象。(被複制的對象可以理解為模板)
原型模式的應用場景
複雜結構對象的創建。
複雜結構對象:可以理解為對象裏面還有對象。
【舉個栗子】:點外賣的收貨地址
收貨地址包括姓名,電話和住址。第一次點外賣的時候需要完整的填寫這些信息,但是之後點的過程基本上是不用再重新填寫這些信息的。試想一下,每次下單之前都要填一遍姓名,電話,詳細地址(假設省市已經定位好了)。頭大…..而這個場景,正是原型模式的用武之地。
點外賣之前複製上一次填寫的地址,直接下單;或者手機號出現變更,修改一下直接更新到模板即可。
原型模式的本質是創建一個對象模板,然後通過複製的方式實現復用。
深拷貝(複雜對象一波帶走)
在深拷貝之前,簡單聊一下淺拷貝。
以上述收貨地址為例,如果只涉及到姓名,電話這些基本數據類型(淺拷貝與深拷貝是基本沒有區別的),但是如果涉及到地址這樣的引用類型。淺拷貝就會出現問題。淺拷貝對於引用對象,只複製其引用地址。所以複製出來的對象和被複制的對象會指向同一個值。假設你想建立兩個收貨模板,地址是不同的,那麼就只能使用深拷貝了。
擼段代碼試試看:
思路:
1.創建Info類和Address類繼承Serializable接口,為了後面實現序列化寫入內存。(實現平台無關性)
2.Info類還需要繼承Cloneable接口,並重寫clone()方法,註:protected改為public
3.在clone()方法中添加寫入內存和讀取的邏輯
4.Info info1 = (Info) info.clone();創建對象,並可做靈活修改。
import java.io.*; class Address implements Serializable { private String province; private String city; private String Street; private String door_number; public Address(String province, String city, String street, String door_number) { this.province = province; this.city = city; Street = street; this.door_number = door_number; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getStreet() { return Street; } public void setStreet(String street) { Street = street; } public String getDoor_number() { return door_number; } public void setDoor_number(String door_number) { this.door_number = door_number; } @Override public String toString() { return "Address{" + "province='" + province + ''' + ", city='" + city + ''' + ", Street='" + Street + ''' + ", door_number='" + door_number + ''' + '}'; } } class Info implements Cloneable, Serializable //1.創建一個外賣信息類,繼承Cloneable(可複製),Serializable(可序列化) { private String name; private String number; Address address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Info(String name, String number, Address address) { this.name = name; this.number = number; this.address = address; } @Override public String toString() { return "Info{" + "name='" + name + ''' + ", number='" + number + ''' + ", address=" + address + '}'; } @Override public Object clone() throws CloneNotSupportedException { //2.重寫clone方法,並把protected換成public ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject(this); //寫入內存 oos.close(); byte[] bytes = out.toByteArray(); InputStream in = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(in); Object clone = ois.readObject(); //讀取內存 ois.close(); return clone; } catch (Exception e) { throw new RuntimeException(e); } } } /* clone()方法直接複製在內存中已經創建對象的二進制,效率極高!(不需要調用構造器) protected native Object clone() throws CloneNotSupportedException; native修飾的方法直接調用底層的C語言 */ public class MyInfo { public static void main(String[] args) throws CloneNotSupportedException { Info info = new Info("shadow","18116207310",new Address("上海","浦東新區","振南路","355")); System.out.println(info); Info info1 = (Info) info.clone(); //3.複製加強轉 System.out.println(info1); System.out.println("//修改電話:"); Info info2 = (Info) info.clone(); info2.setNumber("123456789"); System.out.println(info2); System.out.println("//修改地址:"); Info info3 = (Info) info.clone(); info3.getAddress().setStreet("西語街"); info3.getAddress().setDoor_number("666"); System.out.println(info3); } }
輸出結果:

