使用特定原型实例来创建特定种类的对象,并且通过拷贝原型来创建新的对象
- 你需要复制一些对象,同时又希望代码独立于这些对象所属的具体类
- 子类的区别仅在于其对象的初始化方式,那么你可以使用该模式来减少子类的数量。别人创建这些子类的目的可能是为了创建特定类型的对象。
-
创建原型接口, 并在其中声明
克隆
方法。 如果你已有类层次结构, 则只需在其所有类中添加该方法即可。 -
原型类必须另行定义一个以该类对象为参数的构造函数。 构造函数必须复制参数对象中的所有成员变量值到新建实体中。 如果你需要修改子类, 则必须调用父类构造函数, 让父类复制其私有成员变量值。
如果编程语言不支持方法重载, 那么你可能需要定义一个特殊方法来复制对象数据。 在构造函数中进行此类处理比较方便, 因为它在调用
new
运算符后会马上返回结果对象。 -
克隆方法通常只有一行代码: 使用
new
运算符调用原型版本的构造函数。 注意, 每个类都必须显式重写克隆方法并使用自身类名调用new
运算符。 否则, 克隆方法可能会生成父类的对象。 -
你还可以创建一个中心化原型注册表, 用于存储常用原型。
你可以新建一个工厂类来实现注册表, 或者在原型基类中添加一个获取原型的静态方法。 该方法必须能够根据客户端代码设定的条件进行搜索。 搜索条件可以是简单的字符串, 或者是一组复杂的搜索参数。 找到合适的原型后, 注册表应对原型进行克隆, 并将复制生成的对象返回给客户端。
最后还要将对子类构造函数的直接调用替换为对原型注册表工厂方法的调用。
优点
- 你可以克隆对象, 而无需与它们所属的具体类相耦合。
- 你可以克隆预生成原型, 避免反复运行初始化代码。
- 你可以更方便地生成复杂对象。
- 你可以用继承以外的方式来处理复杂对象的不同配置。
缺点
- 克隆包含循环引用的复杂对象可能会非常麻烦。
- 在许多设计工作的初期都会使用工厂方法模式 (GOF)(较为简单, 而且可以更方便地通过子类进行定制), 随后演化为使用抽象工厂模式 (GOF)、 原型模式或生成器模式 (GOF) (更灵活但更加复杂)。
- 抽象工厂模式 *(GOF)*通常基于一组工厂方法 (GOF), 但你也可以使用原型模式来生成这些类的方法。
- 原型可用于保存命令模式的历史记录。
- 大量使用组合模式 *(GOF)*和装饰模式 *(GOF)*的设计通常可从对于原型的使用中获益。 你可以通过该模式来复制复杂结构, 而非从零开始重新构造。
- 原型并不基于继承, 因此没有继承的缺点。 另一方面, 原型需要对被复制对象进行复杂的初始化。 工厂方法 *(GOF)*基于继承, 但是它不需要初始化步骤。
- 有时候原型可以作为备忘录模式 *(GOF)*的一个简化版本, 其条件是你需要在历史记录中存储的对象的状态比较简单, 不需要链接其他外部资源, 或者链接可以方便地重建。
- 抽象工厂 (GOF)、 生成器 *(GOF)*和原型都可以用单例模式来实现。