一、原型模式定义
原型模式就是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 当要实例化的类是在运行时动态指定的,或者制定类型的对象创建过程过于复杂,但我们又需要频繁的使用该对象,可以使用原型模式。
二、UML结构图
原型模式主要包含如下三个角色:
Prototype:抽象原型类。声明克隆自身的接口。
ConcretePrototype:具体原型类。实现克隆的具体操作。
Client:客户类。让一个原型克隆自身,从而获得一个新的对象。
三、深拷贝VS浅拷贝
这里要区分两个概念:深拷贝、浅拷贝。
浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值,这个方式被称为浅拷贝。
深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。
四、模式实现
对java语言来说,Object对象本身提供了clone()方法,我们可以通过调用clone()方法来复制一个对象。但是要使用clone()方法,必须要实现Cloneable接口,表示实现接口的该类具有复制能力。如果不实现,则调用clone()方法会抛出CloneNotSupportedException。见下面
Java中任何实现了Cloneable接口的类都可以通过调用clone()方法来复制一份自身然后传给调用者。一般而言,clone()方法满足:
(1) 对任何的对象x,都有x.clone() !=x,即克隆对象与原对象不是同一个对象。
(2) 对任何的对象x,都有x.clone().getClass()==x.getClass(),即克隆对象与原对象的类型一样。
(3) 如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
五、具体例子
@Getter
public class PrototypeDemo implements Cloneable {
private String field1;
public PrototypeDemo(String s) {
field1 = s;
}
public Object clone() {
// 实现方式1
// return new PrototypeDemo(field1);
//实现方式2
PrototypeDemo prototypeDemo = null;
try {
prototypeDemo = (PrototypeDemo) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return prototypeDemo;
}
public static void main(String[] args) throws Exception {
PrototypeDemo demo = new PrototypeDemo("Prototype test");
PrototypeDemo copy = (PrototypeDemo) demo.clone();
System.out.println(copy.getField1());
System.out.println("== 测试 " + (copy == demo));
System.out.println("Class 测试 " + (copy.getClass() == demo.getClass()));
}
}
六、优缺点
优点
(1)当创建对象的实例较为复杂的时候,使用原型模式可以简化对象的创建过程,通过复制一个已有的实例可以提高实例的创建效率。
(2)可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点
(1)需要为每一个类配置一个克隆方法,而且该克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
(2)对象之间的引用较复杂的情况下,实现深拷贝比较复杂
七、适用场景
(1)对象创建成本较大的情况
(2)需要保存对象的状态,所需资源较小的情况