1. 原型模式
1.1 原型模式的定义、优缺点、应用场景
定义:用一个已经创建的实例对象作为原型,通过复制该原型对象来创建一个和原型对象相同或相似的新对象。避免了重复执行耗时耗资源的new构造函数过程
优点:
- Java自带的原型模式(implements Cloneable,然后override clone方法)基于内存二进制流的复制,在性能上比直接new一个对象更加优良
缺点:
- 需要为类配置一个clone方法
- clone方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则
- 当实现深克隆时,如果类的属性是一个Object,则需要对该Object进行复制。且该Object对应的类也需要实现深克隆。如此递归下去,实现很麻烦
应用场景:
- 对象之间相同或相似,即只是个别的几个属性不同的时候
- 创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源
- 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性
- 系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值
1.2 原型模式的结构与实现
结构:
- 具体原型类:实现Cloneable接口并override clone方法
- 通过具体原型类实例化一个对象,然后调用该对象的clone方法复制出新对象
浅克隆和深克隆:
- 浅克隆:创建一个新对象,新对象的属性和原来对象的属性完全相同,因为对象的属性指向的是同一个内存地址
- 深克隆:创建一个新对象,新对象的属性(非基本类型属性)也被克隆
示例如下:
public class PrototypeTest {
public static void main(String[] args) {
Prototype prototype1 = new Prototype("zhang_san", new DeepClone());
Prototype prototype2 = (Prototype) prototype1.clone();
System.out.println("prototype1和prototype2的内存地址是否一样:" + (prototype1 == prototype2));
prototype2.setName("li_si");
}
}
// 用于实现深克隆
class DeepClone implements Cloneable {
public DeepClone() {
}
public Object clone() {
DeepClone deepClone = null;
try {
deepClone = (DeepClone) super.clone();
} catch (CloneNotSupportedException e) {
}
return deepClone;
}
}
// 具体原型类
class Prototype implements Cloneable {
private String name;
private DeepClone deepClone;
public Prototype(String name, DeepClone deepClone) {
this.name = name;
this.deepClone = deepClone;
System.out.println("原型对象创建成功");
}
public String getName() {
return this.name;
}
// 用于对复制的新对象修改属性。实现相似对象的复制功能
public void setName(String name) {
this.name = name;
}
public DeepClone getDeepClone() {
return this.deepClone;
}
public void setDeepClone(DeepClone deepClone) {
this.deepClone = deepClone;
}
public Object clone() {
Prototype prototype = null;
try {
// 实现浅克隆
prototype = (Prototype) super.clone();
// 实现深克隆
prototype.deepClone = (DeepClone) prototype.deepClone.clone();
} catch (CloneNotSupportedException e) {
System.out.println("原型对象复制失败");
}
System.out.println("原型对象复制成功");
return prototype;
}
}
运行程序,结果如下:
原型对象创建成功
原型对象复制成功
prototype1和prototype2的内存地址是否一样:false