原型设计模式只是克隆吗?

18

我正在进行深入的设计模式研究,遇到了原型模式,这是我以前没有真正研究过的。我在网上和几本书中搜索,没有找到一个真正好的原型模式示例,它们都只是克隆。原型模式的设计模式基本上是Java和C#中的一种语言特性,类似于clone吗?


3
设计模式是与语言无关的抽象概念,而克隆(clone)则是一种特定的语言惯用语。可以说原型模式是克隆惯用语的一般化,或者说克隆是原型模式的一种语言特定惯用语,但将其严格地绑定到单一语言的惯用语上是错误的。 - Martin Spamer
3个回答

20

原型模式不仅仅是克隆。克隆语义更广泛,意味着将一个对象实例的标量/值字段复制到新实例中,以使它们具有相同的状态但位于内存中的不同位置。克隆可以用于支持许多不同的需求。

原型模式特别将克隆(Clone)集成进解决将对象的构建与对象的使用分离的大问题中。原型语义表明,构造所需行为的新对象的唯一(或至少是受支持/首选)方法是通过克隆一个特定实例来创建,该实例被称为原型实例。这些原型实例可以存在于原型工厂中,该工厂被实现为通过在原型实例上调用克隆来创建新实例。原型实例可以通过依赖注入进行初始化。注入代码是唯一需要知道如何构建原型实例的代码,这有效地成为真正的工厂代码。

希望以下示例工厂类能澄清模式的关键:

public class PrototypeWidgetFactory : IWidgetFactory
{
  public PrototypeWidgetFactory(PrototypeWidget scenarioA, PrototypeWidget scenarioB, PrototypeWidget scenarioC) 
  {
    _scenarioA = scenarioA;
    _scenarioB = scenarioB;
    _scenarioC = scenarioC;
  }

  public Widget GetForScenarioA() { return _scenarioA.Clone(); }
  public Widget GetForScenarioB() { return _scenarioB.Clone(); }
  public Widget GetForScenarioC() { return _scenarioC.Clone(); }

  private PrototypeWidgetFactory _scenarioA;
  private PrototypeWidgetFactory _scenarioB;
  private PrototypeWidgetFactory _scenarioC;
}

当需要IWidgetFactory时,可以将此工厂的实例传递。优点在于您不需要为每种行为编写一堆不同的工厂类。实际上,对于某些类型的行为,如果您只是将初始化方式不同的相同类型的实例注入原型工厂中,则甚至不需要许多不同的类。在这种情况下,优点更大,因为API不会充斥着许多没有太多作用的小类。

缺点是注入代码需要知道如何构造原型。如果构造原型涉及大量复杂的逻辑,则此方法容易出错。

(注意:原型模式不要求原型工厂上的所有方法返回相同的类型。我只是让示例仅返回Widgets,因为这演示了使用原型为特定行为构造对象时的更大优势,即对象是一个类型但是被不同地初始化。)

public class PrototypeDomainFactory : IDomainFactory
{
  public PrototypeDomainFactory(PrototypePerson personPrototype, PrototypeCompany companyPrototype, PrototypeWidget widgetPrototype) 
  {
    _personPrototype = personPrototype;
    _companyPrototype = companyPrototype;
    _widgetPrototype = widgetPrototype;
  }

  public Person GetPerson() { return _personPrototype.Clone(); }
  public Company GetCompany() { return _companyPrototype.Clone(); }
  public Widget GetWidget() { return _widgetPrototype.Clone(); }

  private PrototypePerson _personPrototype;
  private PrototypeCompany _companyPrototype;
  private PrototypeWidget _widgetPrototype;
}

5

1
这不是原型--(虽然它肯定与之相关)--他称其为属性模式。在JavaScript中,“原型”一词用于描述其中的一部分,并且克隆肯定涉及其中,但我仍然认为它们是不同的东西。GoF中的原型并不涉及动态属性的概念。 - Lou Franco
这是一个很好的观点。我一直认为原型应该包括动态属性和可迭代性,因为如果不包括这些,它基本上就是Clone(),这似乎很无聊。 - David Seiler
哇,感谢发布这篇博客文章。非常不错的阅读材料。我从中学到了很多知识。我同意这不是GoF书中描述的原型模式。 - John Sonmez

0

Clone()肯定是其中一部分。我认为这种模式还讨论了收集对象的方法,迭代它们并找到正确的克隆对象。您还必须先设置好这些对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接