所以,关于工厂的主题,我想知道它们是如何建立的。
从我的立场,我可以看到3种类型的工厂:
All In One
一个工厂,基本上包含应用程序中使用的所有类。感觉它只是为了拥有一个工厂而拥有一个工厂,而且并不真正感觉有条理。
示例(其中ClassA,Class B和ClassC没有任何共同点,除非是在同一个应用程序中):
class Factory
{
public static function buildClassA()
public static function buildClassB()
public static function buildClassC()
}
提供的代码示例使用PHP。但是,这个问题与语言无关。
内置工厂
下一个是将静态函数与常规函数混合,以便创建特殊的创建模式(参见this question)
示例:
class ClassA
{
public static function buildClass()
public function __construct()
}
工厂正面
我能想到的最后一个是为个别班级或个别班级设立工厂。这似乎是变量,以统一的方式使用。
示例(其中ClassA,B和C是相关的,而1,2和3是相关的):
class FactoryAlpha
{
public static function buildClassA()
public static function buildClassB()
public static function buildClassC()
}
class FactoryNumeric
{
public static function buildClass1()
public static function buildClass2()
public static function buildClass3()
}
我的问题是:所有这些糟糕的想法,其中任何一个都是坏主意吗?还有其他创建工厂的方法吗?这些中的任何一个都是好主意吗?什么是创建工厂的好/最佳方式。
答案 0 :(得分:5)
工厂的观点似乎是让使用它的代码不需要知道将构造哪个具体类(这应该通过配置工厂来处理)。这似乎排除了“All-in One”和“Factory-on-the-Side”。
我喜欢Java库经常使用的方法:您有一个创建Factory的静态方法。 Factory具有一个用于创建实例的getInstance方法。这为您提供了两个配置点(通过系统属性):默认的FactoryImpl有许多设置,例如它应该生成的类,如果这些配置选项不够,您也可以完全换掉FactoryImpl。
至于“All-in One”与“Factory-on-the-Side”,工厂不应该生产我认为不相关的课程。同样,它是Java术语,每个工厂都会生成某个接口的实例。
“All-in-One”听起来像是应该用Dependency Injection取代的东西(你有一个产生各种实例并将它们注入应用程序的容器)。
答案 1 :(得分:2)
如果你真的对“首选技术”感兴趣,我会用依赖注入替换它们。
如果这看起来很重,请记住您可能没有看到工厂的所有用途,所以不要在工厂中“新建”硬编码类。相反,有一个“Setter”可以指定需要注入的类。
当你进行单元测试并需要开始注入模拟类时,这将会派上用场。
但是当你使这个更通用,更抽象和可重复使用时,你最终会回到DI。 (只是不要说我没有警告你)
答案 2 :(得分:0)
实际上只有两种标准种类的工厂,至少根据GOF和slew patterns本followed本书Factory:基本Abstract Factory,和Single Responsibility Principle。
工厂通常会返回调用者通过接口引用的具体实例,如下所示:
// createWidget() here instantiates a BigWidget or SmallWidget or whatever the context calls for
IWidget widget = WidgetFactory.createWidget(someContextValue);
以这种方式使用带有接口的工厂可以防止调用者耦合到返回对象的特定类型。在古老的Dependency Inversion之后,工厂应该做一件事,就是返回被调用的接口的具体实例,仅此而已。基础工厂应该只能创建一种类型的对象。
另一方面,抽象工厂可以被认为是工厂的工厂,可能更接近你所认为的“一体化”工厂。抽象工厂通常在启动时配置为返回一组相关工厂,例如可能根据给定上下文创建特定GUI系列的工厂。这是Spring的一个示例,很大程度上已经被{{3}}等IOC容器所取代。