原型模式(Prototype Pattern)指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象,属于创建型设计模式。
以系统中已经存在的对象为原型,直接基于内存二进制流进行复制,不会调用构造函数,也不需要再进行初始化的过程,大大缩短创建时间。
使用场景
(1)创建对象成本较大(例如,初始化时间长,占用CPU太多,或者占用网络资源太多等),需要优化资源。
(2)创建一个对象需要烦琐的数据准备或访问权限等,需要提高性能或者提高安全性。
(3)一个对象被多个修改者修改。系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值。每个修改者自己克隆一个拷贝,然后修改拷贝。
实现方式:
实现Cloneable接口,重写clone()方法。如果没有实现Cloneable接口,调用clone方法会抛出CloneNotSupportedException异常。
浅拷贝
基础数据类型会被拷贝,数组和引用对象指向相同的实例,只是指针拷贝了副本,复制了引用的地址
Cloneable接口的clone方法是浅拷贝
深拷贝
基础数据类型会被拷贝,数组和引用对象指向不同的实例,实例的值进行了拷贝
- 序列化后反序列化
- 重写clone方法,手动给克隆对象的相关属性分配另一块内存
public class MyPrototype implements Cloneable, Serializable {private String code;private List<String> list;@Overridepublic MyPrototype clone() {try{return (MyPrototype)super.clone();}catch (CloneNotSupportedException e){e.printStackTrace();return null;}}public MyPrototype deepClone(){try{//设置写缓冲ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);//往写缓冲中写入oos.writeObject(this);//写缓冲中复制到读缓冲ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);//从读缓冲中读取return (MyPrototype)ois.readObject();} catch (Exception e) {e.printStackTrace();return null;}}...}
框架:
spring的@Scope(“prototype”)
反序列化JsonObject.parseObject()
原型模式的优点
- Java自带的原型模式基于内存二进制流的复制,不会进行初始化, 不会执行构造函数, 在性能上比直接new一个对象更加优良。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
原型模式的缺点
- 需要为每一个类都配置一个clone方法。
- clone方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
