原型模式最早出现于 1963 年的一个叫 Sketchpad 的系统中,说起 Sketchpad 你可能并不熟悉,但是说起 CAD(计算机辅助设计),现在在工程设计领域几乎无人不知,其实 Sketchpad 就被认为是现代 CAD 程序的鼻祖,主要思想是拥有一张可以实例化成许多副本的原图,如果用户更改了主工程图,则所有实例也会更改。这便是原型模式最初的思维模型。
不过在面向对象编程中,对象的原型在变化时通常不会影响新实例对象。实际上,原型模式不仅在 Java、C++ 等主要基于类的编程语言中有广泛应用,而且还在一开始就是基于原型的 JavaScript 等编程语言中得到了发扬光大。原型模式的原理与使用其实很简单,但是要想用好它,我们除了要了解它的优点以外,更要重点注意它带来的问题以及掌握如何规避这些问题。下面,我们就一起来看看吧。
一、模式原理分析
原型模式的定义是:使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
你可以看到,定义中清晰地指出了两个关键点,一个是要建立原型,另一个是基于原型做拷贝。原理很简单,在现代编程中,我们经常会用到的 Ctrl+C 加 Ctrl+V 编程,可以说就是最直接的原型模式的实践之一。
我们来看看原型模式原始的 UML 图:
从这个 UML 图中,我们可以看到原型模式中的关键角色有三个:
-
使用者;
-
原型;
-
新实例。
使用者需要建立一个原型,才能基于原型拷贝出新实例。除此之外,使用者还需要决策什么时候使用原型、什么时候使用新实例,以及从原型到新实例之间的拷贝应该采用什么样的算法策略,这些都是使用者来进行控制和决定的。只不过通常我们会使用一个通用的抽象拷贝接口来对外提供拷贝。
那 UML 图对应的代码该怎么实现呢?可参考下面这段基于 Java Cloneable 接口的代码实现:
public interface PrototypeInterface extends Cloneable {
PrototypeInterface clone() throws CloneNotSupportedException;
}
public class ProtypeA implements PrototypeInterface {
@Override