概念
原型模式就是从一个对象再创建另外一个可定制的对象, 而且不需要知道任何创建的细节。
所谓原型模式, 就是 Java 中的克隆技术, 以某个对象为原型。 复制出新的对象。 显然新的对象具备原型对象的特点, 效率高(避免了重新执行构造过程步骤)。
原型模式主要适用于以下场景:
- 类初始化消耗资源较多。
- new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
- 构造函数比较复杂。
- 循环体中生产大量对象时。
浅拷贝和深拷贝的特点
浅拷贝
- 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。
- 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
深拷贝
- 复制对象的所有基本数据类型的成员变量值
- 为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象图进行拷贝!
总结:
深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间
原型模式类图:
![prototype]()
Java中原型模式的浅拷贝和深拷贝的实现方式
- 浅拷贝: 通过重写clone()方法进行浅拷贝,需要实现Clonable接口
- 深拷贝: 通过对象序列化实现深拷贝,推荐使用JSON序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| @Getter @Setter public class ConcretePrototypeA implements Cloneable, Serializable { private int age; private String name; private List<String> hobbies;
@Override public Object clone() throws CloneNotSupportedException { return super.clone(); }
public Object 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 ois.readObject(); } catch (Exception e) { throw new RuntimeException("深拷贝失败!", e); } }
public ConcretePrototypeA deepCloneWithJSON() { String jsonString = JSON.toJSONString(this); return JSON.parseObject(jsonString, this.getClass()); } }
|
深拷贝第二种方式:先调用super.clone()方法克隆出一个新对象来,然后在子类的clone()方法中手动给克隆出来的非基本数据类型(引用类型)赋值。太麻烦,不推荐使用。
源码:https://github.com/chentianming11/design-pattern
prototype包!