原型模式

用于克隆对象。

利用场景:

  1. 因为拷贝要比从新创立一个对象快得多,所以当创立一个对象所耗资源很多时,能够思考应用拷贝。
  2. 避免原对象被批改,例如在并发环境下的一个ArrayList,若须要批改其中的值又怕会引起并发批改异样,能够思考克隆后操作,即保护性拷贝。

浅拷贝

实现Cloneable接口,重写clone()办法。

 public class Sheep implements Cloneable{  private String id;  private String name;  private int age;  private Sheep friend;   public Sheep() {  }   public Sheep(String id, String name, int age, Sheep friend) {  this.id = id;  this.name = name;  this.age = age;  this.friend = friend;  }   public String getId() {  return id;  }   public void setId(String id) {  this.id = id;  }   public String getName() {  return name;  }   public void setName(String name) {  this.name = name;  }   public int getAge() {  return age;  }   public void setAge(int age) {  this.age = age;  }   public Sheep getFriend() {  return friend;  }   public void setFriend(Sheep friend) {  this.friend = friend;  }   @Override  public String toString() {  return "Sheep{" +  "id='" + id + ''' +  ", name='" + name + ''' +  ", age=" + age +  ", friend=" + friend +  '}';  }   @Override  public Sheep clone() throws CloneNotSupportedException {  return (Sheep) super.clone();  } }

测试

 public class Main {  public static void main(String[] args) throws CloneNotSupportedException {  Sheep sheep = new Sheep();  sheep.setAge(1);  sheep.setName("teddy");  sheep.setFriend(new Sheep("1","tom",1,null));   Sheep cloneSheep=sheep.clone();   System.out.println(sheep);  System.out.println(cloneSheep);   System.out.println(sheep.hashCode());  System.out.println(cloneSheep.hashCode());   System.out.println(sheep.getFriend().hashCode());//援用是同一个  System.out.println(cloneSheep.getFriend().hashCode());  } }

输入

 Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}} Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}}  1956725890 356573597  1735600054 1735600054

阐明浅拷贝无奈克隆援用。

深拷贝

一、应用clone()

同样实现Cloneable()接口,

将clone办法批改为

  @Override  public Sheep clone(){  Sheep sheep=null;  try {  sheep=(Sheep) super.clone();  Sheep friendSheep = sheep.getFriend();  if (friendSheep!=null){  sheep.setFriend(friendSheep.clone());  }  } catch (CloneNotSupportedException e) {  e.printStackTrace();  }  return sheep;  }

留神:援用类型克隆前要判空。

测试输入:

 Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}} Sheep{id='null', name='teddy', age=1, friend=Sheep{id='1', name='tom', age=1, friend=null}}  607635164 529116035  242481580 1627800613
二、序列化
 public Sheep deepClone(){  ByteArrayOutputStream out;  ByteArrayInputStream in = null;  ObjectInputStream oin = null;  ObjectOutputStream oout=null;  out = new ByteArrayOutputStream();  try {  oout=new ObjectOutputStream(out);  oout.writeObject(this);  //要保障out中有内容写入,不然会报EOFException  in = new ByteArrayInputStream(out.toByteArray());  oin=new ObjectInputStream(in);  return (Sheep) oin.readObject();  } catch (IOException | ClassNotFoundException e) {  e.printStackTrace();  }finally {  try {  if (oin!=null) {  oin.close();  }  if (oout!=null){  oout.close();  }  out.close();  if (in != null) {  in.close();  }  } catch (IOException e) {  e.printStackTrace();  }  }  return null;  }

流程:

  1. 实例化ByteArrayOutputStream;
  2. 实例化ObjectOutputStream;
  3. 写入对象
  4. 实例化ByteArrayInputStream
  5. 实例化ObjectInputStream
  6. 读出对象

留神:写入对象肯定要在实例化输出流之前,因为实例化ByteArrayInputStream传入输入流,以输入流中的内容读出对象,若输入流中没有内容,会在实例化ByteArrayInputStream时抛出EOFException。