創建型模式————原型模式(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);      }  }

輸出結果: