Java教程

6.原型模式prototype

本文主要是介绍6.原型模式prototype,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

该模式的作用就是复制对象,特别是复杂的对象。

1.浅克隆

两个要点:实现Cloneable接口,重写clone()方法

public class Product implements Cloneable{

  private String name;
  private Date date;

  public Product(String name, Date date) {
    this.name = name;
    this.date = date;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Date getDate() {
    return date;
  }

  public void setDate(Date date) {
    this.date = date;
  }

  @Override
  public String toString() {
    return "Product{" +
        "name='" + name + '\'' +
        ", date=" + date +
        '}';
  }

  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}  

测试结果:

//浅克隆
  public static void main(String[] args) throws CloneNotSupportedException {
    Date date1 = new Date();
    Product product = new Product("张三",date1);
    System.out.println("v1=>"+product +" hashcode=>"+product.hashCode());

    Product cloneProduct = (Product) product.clone();
    System.out.println("v2=>"+cloneProduct+" hashcode=>"+cloneProduct.hashCode());

    date1.setTime(22223333);
    System.out.println("===========修改属性后========");

    System.out.println("v1=>"+product +" hashcode=>"+product.hashCode());
    System.out.println("v2=>"+cloneProduct+" hashcode=>"+cloneProduct.hashCode());
  }

  打印结果:

v1=>Product{name='张三', date=Sun Apr 18 16:45:56 CST 2021} hashcode=>1836019240
v2=>Product{name='张三', date=Sun Apr 18 16:45:56 CST 2021} hashcode=>325040804
===========修改属性后========
v1=>Product{name='张三', date=Thu Jan 01 14:10:23 CST 1970} hashcode=>1836019240
v2=>Product{name='张三', date=Thu Jan 01 14:10:23 CST 1970} hashcode=>325040804

  结论:原对象和克隆对象的date属性是同一个

2.深克隆

解决上个案例中date属性指向同一个问题。

public class Product implements Cloneable{

  private String name;
  private Date date;

  public Product(String name, Date date) {
    this.name = name;
    this.date = date;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Date getDate() {
    return date;
  }

  public void setDate(Date date) {
    this.date = date;
  }

  @Override
  public String toString() {
    return "Product{" +
        "name='" + name + '\'' +
        ", date=" + date +
        '}';
  }

  @Override
  protected Object clone() throws CloneNotSupportedException {
    Product product = (Product)super.clone();
    product.date = (Date) this.date.clone();
    return product;
  }
}

  测试结果

//深克隆
  public static void main(String[] args) throws CloneNotSupportedException {
    Date date1 = new Date();
    Product product = new Product("张三",date1);
    System.out.println("v1=>"+product +" hashcode=>"+product.hashCode());

    Product cloneProduct = (Product) product.clone();
    System.out.println("v2=>"+cloneProduct+" hashcode=>"+cloneProduct.hashCode());

    date1.setTime(22223333);
    System.out.println("===========修改属性后========");

    System.out.println("v1=>"+product +" hashcode=>"+product.hashCode());
    System.out.println("v2=>"+cloneProduct+" hashcode=>"+cloneProduct.hashCode());
  }

  打印:

v1=>Product{name='张三', date=Sun Apr 18 16:56:55 CST 2021} hashcode=>1836019240
v2=>Product{name='张三', date=Sun Apr 18 16:56:55 CST 2021} hashcode=>325040804
===========修改属性后========
v1=>Product{name='张三', date=Thu Jan 01 14:10:23 CST 1970} hashcode=>1836019240
v2=>Product{name='张三', date=Sun Apr 18 16:56:55 CST 2021} hashcode=>325040804

  结论:实现的深克隆,date对象也成功克隆,这里有个前提,Date类也实现了Cloneable接口才行。

3.通过序列化来复制对象

深度克隆有个问题:所有属性都要克隆,属性下面可能还有属性,需要层层克隆,非常麻烦,通过流来复制可以减少这些麻烦,但是IO流会增加系统消耗。

前提是被序列化的对象实现Serializable接口,包括它的层层下面的属性,如果某个属性不想序列化,可以通过一些注解来忽略。

public class Product implements Serializable {

  private String name;
  private Date date;

  public Product(String name, Date date) {
    this.name = name;
    this.date = date;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Date getDate() {
    return date;
  }

  public void setDate(Date date) {
    this.date = date;
  }

  @Override
  public String toString() {
    return "Product{" +
        "name='" + name + '\'' +
        ", date=" + date +
        '}';
  }
}

  测试代码

public class CloneObject {

  public static void main(String[] args) {
    Date date1 = new Date();
    Product product = new Product("张三",date1);
    System.out.println("v1=>"+product +" hashcode=>"+product.hashCode());

    Product product1 = cloneUtil.cloneObject(product);
    System.out.println("v2=>"+product1 +" hashcode=>"+product1.hashCode());

    date1.setTime(22223333);
    System.out.println("===========修改属性后========");
    System.out.println("v1=>"+product +" hashcode=>"+product.hashCode());
    System.out.println("v2=>"+product1 +" hashcode=>"+product1.hashCode());


  }
}
class cloneUtil {
  private cloneUtil() {
  }

  @SuppressWarnings("unchecked")
  public static <T extends Serializable> T cloneObject(T obj) {
    T cloneObj = null;

    // 序列化
    ByteArrayOutputStream bout = null;
    ObjectOutputStream oos = null;
    try {
      bout = new ByteArrayOutputStream();
      oos = new ObjectOutputStream(bout);
      oos.writeObject(obj);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      close(oos);
      close(bout);
    }

    // 反序列化
    ByteArrayInputStream bin = null;
    ObjectInputStream ois = null;
    try {
      bin = new ByteArrayInputStream(bout.toByteArray());
      ois = new ObjectInputStream(bin);
      cloneObj = (T) ois.readObject();
    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
    } finally {
      close(ois);
      close(bin);
    }

    return cloneObj;
  }

  private static void close(Closeable closeable) {
    if (closeable != null) {
      try {
        closeable.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
}

  打印结果:

v1=>Product{name='张三', date=Sun Apr 18 17:03:19 CST 2021} hashcode=>1836019240
v2=>Product{name='张三', date=Sun Apr 18 17:03:19 CST 2021} hashcode=>1072408673
===========修改属性后========
v1=>Product{name='张三', date=Thu Jan 01 14:10:23 CST 1970} hashcode=>1836019240
v2=>Product{name='张三', date=Sun Apr 18 17:03:19 CST 2021} hashcode=>1072408673

  

这篇关于6.原型模式prototype的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!