先想一下既然要创建新的实例,为什么不直接使用 new XXX(),而要设计出一个原型模式进行实例的复制呢?
这是因为:
有的时候,我们也会在不指定类名的前提下生成实例,例如像图形编辑器中拖动现有的模型工具制作图形的实例,这种是非常典型的生成实例的过程太过复杂,很难根据类来生成实例场景,因此需要根据现有的实例来生成新的实例。
原型设计模式主要分为深克隆和浅克隆。
浅克隆 vs 深克隆
clone() 方法使用的是浅克隆。浅克隆对于要克隆的对象, 会复制其基本数据类型和 String 类型的属性的值给新的对象. 而对于非基本数据类型的属性,例如数组、集合, 仅仅复制一份引用给新产生的对象, 即新产生的对象和原始对象中的非基本数据类型的属性都指向的是同一个对象。
此外,还存在深克隆。深克隆对于要克隆的对象, 对于非基本数据类型的属性,例如数组、集合支持复制。换句话说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
浅克隆和深克隆的主要区别在于,是否支持引用类型的成员变量的复制。。
浅克隆的实现分为三点:
1.将该类实现clonable接口;
2.并覆盖Object的clone方法,设置为public关键字,原方法为protected;
3.在clone()中调用super.clone();
代码内容比较简单就不贴了,
深克隆主要分为两种实现:
第一种是通过序列化,将对象写入对象流再读出生成对象即可完成深克隆。
第二种就是在重写的方法对于每个引用对象(即基本类型和String类型以外)的引用继续初始化或者叫单独克隆,即可完成深克隆。
1.改写clone方法完成深克隆
/**
* @author Jay
* @date 2020/7/14 17:09
* @Description:
*/
public class ShallowPrototype implements Cloneable {
private String name;
private Son son;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Son getSon() {
return son;
}
public void setSon(Son son) {
this.son = son;
}
@Override
protected Object clone() throws CloneNotSupportedException {
ShallowPrototype sample= (ShallowPrototype) super.clone();
if (sample!=null){
ShallowPrototype clone = (ShallowPrototype) sample.clone();
}
return super.clone();
}
}
2.通过序列化完成深克隆
ByteArrayOutputStream byteOut=new ByteArrayOutputStream();
ObjectOutputStream outputStream=new ObjectOutputStream(byteOut);
outputStream.writeObject(prototype);
//读出对象;
ByteArrayInputStream byteIN=new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream inputStream=new ObjectInputStream(byteIN);
ShallowPrototype prototype2 = (ShallowPrototype) inputStream.readObject();
inputStream.close();
byteIN.close();
outputStream.close();
byteOut.close();