创建者模式-原型模式
# 概念
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式的克隆分为浅克隆和深克隆。
浅克隆: 创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆: 创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
# 结构
原型模式包含如下角色:
- 抽象原型类:规定了具体原型对象必须实现的的 clone () 方法。
- 具体原型类:实现抽象原型类的 clone () 方法,它是可被复制的对象。
- 访问类:使用具体原型类中的 clone () 方法来复制新的对象。
# 使用场景
资源优化场景: 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
性能和安全要求的场景: 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
一个对象多个修改者的场景: 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
笔记
DTO 转 Entity 的场景就是使用了原型模式,基于安全考虑,不允许更新 createTime
、 updateTime
等字段,因此使用 DTO 接收允许更新的属性,再拷贝到 Entity 对象持久化。
class Student{
private Long id;
private String name;
private String remark;
private Date createTime;
private Date updateTime;
}
class StudentUpdateDTO{
private Long id;
private String name;
private String remark;
}
# 优点
原型模式实际上就是实现 Cloneable
接口,重写 clone()
方法。
性能优良: 原型模式是在内存中二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
逃避构造函数的约束: 这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。
# 代码示例
Java 中的 Object 类中提供了 clone()
方法来实现浅克隆。 Cloneable 接口是上面的类图中的抽象原型类,而实现了 Cloneable 接口的子实现类就是具体的原型类。
public class PrototypeClass implements Cloneable{
//覆写父类 Object 方法
@Override
public PrototypeClass clone(){
PrototypeClass prototypeClass = null;
try {
prototypeClass = (PrototypeClass)super.clone();
} catch (CloneNotSupportedException e) {
//异常处理
}
return prototypeClass;
}
}
# 总结
通过原型模式克隆出来的对象与原对象地址不相同,即 oldObject != newObject
,但如果使用的是浅拷贝则对象中的属性地址相同,深拷贝则不相同。
值得注意的是无论是深、浅拷贝,如属性为基本数据类或 String 类型 (不可变性) 都会指向新地址,即 oldObject.getName() != newObject.getName()