定义

通过原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

结构和说明

创建型模式-原型模式 - 图1

示例代码

  1. public class PrototypeDemo {
  2. public static interface Prototype {
  3. /**
  4. * 克隆自身的方法
  5. *
  6. * @return 一个从自身克隆出来的对象
  7. */
  8. Prototype clone();
  9. }
  10. public static class ConcretePrototype1 implements Prototype {
  11. @Override
  12. public Prototype clone() {
  13. ConcretePrototype1 obj = new ConcretePrototype1();
  14. // 复制属性
  15. return obj;
  16. }
  17. }
  18. public static class ConcretePrototype2 implements Prototype {
  19. @Override
  20. public Prototype clone() {
  21. ConcretePrototype2 obj = new ConcretePrototype2();
  22. // 复制属性
  23. return obj;
  24. }
  25. }
  26. public static class Client {
  27. private Prototype prototype;
  28. public Client(Prototype prototype) {
  29. this.prototype = prototype;
  30. }
  31. public void operation() {
  32. Prototype newPrototype = this.prototype.clone();
  33. }
  34. }
  35. }

调用顺序

创建型模式-原型模式 - 图2

优缺点

优点

  • 对客户端隐藏具体实现类型

原型模式的客户端只知道原型接口的类型,并不知道具体的实现类型,从而减少了客户端对这些具体实现类型的依赖。

  • 在运行时动态改变具体的实现类型

原型模式可以在运行期间,由客户来注册符合原型接口的实现类型,也可以动态地改变具体的实现类型,看起来接口没有任何变化,但其实云心的已经是另外一个类实例了。因为克隆一个原型就类似于实例化一个类。

缺点

原型模式最大的缺点是在于每个子类都必须实现 clone 的操作,尤其在包含引用类型的对象时, clone 方法会比较麻烦,必要要能够递归地让所有相关对象都要正确地实现克隆。

思考

本质

克隆生成对象。

何时选用

  • 如果一个系统想要独立于它想要使用的对象时,可以使用原型模式,让系统中面向接口编程,在系统需要新的对象时,可以通过克隆原型来得到。
  • 如果需要实例化的类是在运行时动态指定时,可以使用原型模式,通过克隆原型来得到需要的实例。

相关模式

  • 原型模式和抽象工厂模式

功能上有些相似,都是用来获取一个新的对象实例的。
不同之处在于,原型模式的着眼点是如果创建出实例对象来,最后选择的方案是克隆;而抽象工厂的着眼点则在于如何来创造产品簇,至于具体如果创建产品簇的每个对象实例,抽象工厂不是很关注。
正是因为他们的关注点不一样,所以它们也可以配合使用,比如在抽象工厂模式里面,具体创建每一种产品的时候就可以使用该产品的原型,也就是抽象工厂管产品簇,具体的每种产品怎么创建则可以选择原型模式。

  • 原型模式和生成器模式

这两种模式可以配合使用。
生成器模式关注的是构建的过程,而在构建的过程中,很可能需要某个部件的实例,那么很自然地就可以应用上原型模式,通过原型模式来得到部件的实例。