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

输出结果: