38

这是关于工厂模式的。我有点困惑。

我看到了createInstance()方法是静态的实现和一些非静态的实现。

有人说这取决于“风格”或“品味”,有人说不是。根据四人帮的说法,维基百科说它应该是非静态的, http: //www.dofactory.com/Patterns/PatternFactory.aspx也说它应该是非静态的。

我的问题是:它是否取决于风格和品味,或者如果它以静态方式实现,它是否违反了工厂模式?什么是对的?

4

3 回答 3

49

我很犹豫将“实例与静态”归类为品味问题。这种类型暗示它的美学就像最喜欢的颜色,或者更恰当地说,camelCase 与 PascalCase。

实例与静态更多的是权衡问题。使用任何类型的实例成员,您都可以获得多态性的所有好处,因为当您拥有实例和实例成员时,您可以实现接口并从其他类继承。使用静力学,您不会获得这些好处。通常,静态与实例是前期简单性与下游简单性的权衡。静态很容易,因为它们是全局可访问的,您不必考虑诸如“何时应该实例化它以及由谁实例化?”之类的事情。您不必使用访问器/修改器或构造器传递它们,并且您的 API看起来更干净。这使得前期推理更容易。但是,它使维护和未来的实施变得更加困难。

如果你有一个静态方法——比如你的工厂方法——然后你希望它在某些情况下表现得不同,那么你就有点受不了了。您必须创建第二种方法并复制并粘贴功能减去您想要更改的任何内容,然后让客户弄清楚。或者,更糟糕的是,您公开了一个全局变量,并让客户在使用您的方法之前和之后设置它,而全局变量告诉方法如何表现。

如果您已经预先设置了实例路线,这将很容易。您只需继承和覆盖您的初始工厂方法,并在您需要新功能的地方提供派生类。您不会给客户端代码增加额外的负担,并且您几乎不会对现有类进行任何修改(开放/封闭原则)。

My advice would be to do future you and/or other maintainers a favor and use the instance implementation. It's not a matter of what the Gang of Four or anyone else want or prefer - it's a matter of your own sanity in the face of code rot.

于 2011-10-26T20:33:17.620 回答
22

静态方法不违反模式,但它违背了许多其他面向对象的做法(控制反转+依赖注入作为一个例子),所以使用实例更好。

编辑:

我刚刚得到了这个答案的一些徽章,但是当我读到它时,我简直不敢相信自己的眼睛。当我们严格地谈论 GoF 工厂方法模式时,它是错误的,它值得一些纠正。

您可以使用静态CreateInstance方法来创建一个类型的实例——这并没有错——人们经常称它为工厂方法,但这不是所谓的工厂方法模式。一旦您开始将逻辑放入此方法中以根据某些条件创建不同类型的实例,您可能实际上需要 GoF 描述的工厂方法模式。

GoF工厂方法模式的重点是CreateInstance用继承和多态替换内部的条件逻辑,因此它不能是静态的。工厂方法是一个实例方法——而且它是虚拟的。您的基本类型通常具有抽象CreateInstance和条件逻辑,被继承树替换,其中每个子类型覆盖CreateInstance并仅为该子类型创建特定产品。

于 2011-10-26T20:19:27.740 回答
7

如果它是一个abstract factory然后实例级别是正常的。并且实例级别的功能往往比static级别更容易模拟和单元测试

于 2011-10-26T20:16:35.483 回答