3.4-Prototype-原型-创建型方法
用途
用原型指定创建对象的种类,拷贝这些原型创建新的对象
示例

例如采用工具类操作图形元素:
- 若为每个图形元素创建相应工具类,则过于冗杂
- 采用原型方法:
- 工具类拷贝一个图形元素的实例,添加到文档中
适用情形
- 当一个系统应该独立于它的产品创建、构成和表示时。
- 当要实例化的类是在运行时指定时,例如,通过动态装载。
- 为了避免创建一个与产品类层次平行的工厂类层次时。
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
结构
- Prototype:提供 clone 自身的接口
- ConcretePrototype:实现 clone 的操作
- Client:用原型 clone 自身从而创建新的对象

优缺点
Prototype 有许多与 Abstract Factory(3.1)和 Builder(3.2)一样的效果:
- 它对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。
- 此外,这些模式使客户无须改变自身代码即可使用与特定应用相关的类。
其他优点:
- 运行时增加和删除产品
- 改变值以指定新对象:高度动态的系统允许你通过对象组合定义新的行为——例如,通过为一个对象变量指定值——并且不定义新的类。 克隆一个原型类似于实例化一个类。Prototype 模式可以极大地减少系统所需要的类的数目。
- 改变结构以指定新对象许多应用由部件和子部件来创建对象。
- 例如电路设计编辑器就是由子电路来构造电路的:这样的应用通常允许你实例化复杂的、用户定义的结构,比方说,一次又一次地重复使用一个特定的子电路。
- Prototype 模式只要组合电路对象将 Clone 实现为一个深拷贝(deep copy),具有不同结构的电路就可以是原型了。
- 减少子类的构造:Factory Method(3.3)经常产生一个与产品类层次平行的 Creator 类层次。Prototype 模式使得你克隆一个原型而不是请求一个工厂方法去产生一个新的对象,因此你根本不需要 Creator 类层次。
- 主要适用于像 C++这样不将类作为一级类对象的语言(通常是静态语言)。这种语言中,类本身不是一种对象,而是一种特殊的数据类型或结构。这意味着,这种语言中,类不能被当作参数传递给函数,也不能被当作返回值返回,也不能被动态创建或销毁。例如,C++中的类只能在编译时静态定义,而不能在运行时动态生成或修改。
- 相反,将类作为一级类对象的语言(通常是动态语言),则认为类本身也是一种对象,只不过是用来创建其他对象的对象。这意味着,这种语言中,类可以被当作参数传递给函数,也可以被当作返回值返回,也可以被动态创建或销毁。例如,Python 就是一种将类作为一级类对象的语言,因为 Python 中的类是由 type 这个元类创建的对象,而且可以在运行时动态生成或修改2。
- 用类动态配置应用一些运行时环境允许你动态地将类装载到应用中。
- 一个希望创建动态载入类的实例的应用不能静态引用类的构造器,而应该由运行环境在载入时自动创建每个类的实例,并用原型管理器来注册这个实例。这样应用就可以向原型管理器请求新装载的类的实例,这些类原本并没有和程序相连接。
缺陷:
- 每个 Prototype 子类必须实现 clone 操作,而这可能非常困难
实现
在像 C++这样的静态语言中,类不是对象,并且运行时只能得到很少或者得不到任何类型信息,所以 Prototype 特别有用。 相反,在类似 Python 这样的语言中意义不大,语言自带等价于原型的东西(类对象、元类等)
具体实现有以下要点:
- 实现原型管理器:当一个系统中原型数目不固定时(也就是说,它们可以动态创建和销毁),要保持一个可用原型的注册表,以便用户存储和检索原型。
- 原型管理器根据关键字返回相匹配的原型(即,~是一种关联存储器)
- 实现对象克隆操作:这是最困难的环节(当对象结构包含循环引用时,这尤为棘手):
- 深浅拷贝:
- 深拷贝:克隆一个对象是依次克隆它的实例变量
- 浅拷贝:由克隆对象和原对象共享这些变量(拷贝的对象和原来的对象之间是共享指针)
- 大多数语言都对克隆对象提供了一些支持(例如 C++提供了一个拷贝构造器),这通常是浅拷贝
- 克隆一个结构复杂的原型通常需要深拷贝,因为复制对象和原对象必须相互独立。
- 深浅拷贝:
- 初始化克隆对象:使用初始化参数并据此设定克隆对象的内部状态
- 注意深拷贝 Clone 操作——一些副本在你重新初始化它们之前可能必须要删除掉
相关模式
Prototype 和 Abstract Factory(3.1)模式在某些方面是相互竞争的。
- 但是它们也可以一起使用:Abstract Factory 可以存储一个被克隆的原型的集合,并且返回产品对象。 大量使用 Composite(4.3)和 Decorator(4.4)模式的设计通常也可从 Prototype 模式获益。