如何初始化工厂?

时间:2018-10-29 06:57:23

标签: design-patterns dependency-injection inversion-of-control factory-pattern

我有一个工厂来制造汽车...它是一个基本工厂,它接受汽车的名称,查找实现1. feeds ( id, user_id, type, object_id) 2. badge ( id, 'badge_name', 'slug' ) 3. Post (id, 'post_name', 'post_type') 的所有类,根据汽车名称选择正确的类型,并使用来初始化汽车反思。

ICar

现在,我有一个使用public class CarFactory { Dictionary<string, Type> cars; public ICar CreateInstance(string carName) { // choose type of class from all classes that implement ICar Type t = GetTypeToCreate(carName); return Activator.CreateInstance(t) as ICar; } // some more code... } 的服务。在服务中初始化CarFactory的正确方法是什么?

一种解决方案是注入工厂,但是 Factory Pattern是IoC本身的一种形式,注入工厂感觉很奇怪。根据{{​​3}}:

  

与IoC一起使用工厂没有多大意义,因为   IoC容器在某种意义上是“通用抽象工厂”。

     

换句话说,根据我的经验,任何时候我想添加一个   我最终以更简单的基于IoC的解决方案作为工厂,这就是为什么我   敢说“ IoC杀死工厂之星”

上面的内容对我来说很有意义,尽管我还没有想到用DI代替Factory的解决方案。

所以我的问题是(对于那些使用工厂模式的人)我应该如何初始化它?


为避免问题过长,我在此问题中使用了一个简化的CarFactory示例。我已经发布了完整的示例Nikola Malovic

3 个答案:

答案 0 :(得分:1)

最好将依赖项(构造函数,属性,方法)注入您的类型中。最好避免使用new-operator创建依赖关系。

要使其变得更好,您应该为您CarFactoryICarFactory)定义一个接口,并根据该类型更改服务。

在测试中,您可以模拟ICarFactory并为测试用例提供特殊的实现。

答案 1 :(得分:1)

我认为比较依赖注入容器和工厂是错误的。
是的,这两种责任都是创建某种类型的实例。

但是DI容器负责根据DI配置实例化实例及其所有依赖项。通常,DI容器在应用程序的入口点(main方法或Web应用程序中的request)实例化对象。

Factory将根据您的应用程序的某些业务逻辑或某些只能在运​​行时访问的值创建该类型的实例。

Factory与其他类一样是普通类,可以将其作为依赖项注入。

在您的特定情况下,您仅在运行时知道汽车的名称,因此您将需要一些类,其职责是将名称“转换”为汽车的实例。

答案 2 :(得分:1)

像往常一样,对于此类问题,答案是 It Depends™。这取决于您要解决的问题。尽管此问题同时带有依赖注入控制反转(在the same idea级别)标记,但这些都不是目标,而仅仅是一种实现适当目标的方法。

通常,目标是将行为去耦。这导致了第一个问题,然后:

为什么CreateInstance返回ICar实例?

我在这里假设ICar是一个接口。 ICar是多态的吗?您是否有该接口的多个实现?

一个名为 car 的对象在我看来像实体,而那些should usually not be injected听起来像实体,因为它们通常表示数据,而不是行为。

不过,为了讨论起见,我们假设ICar确实是多态的。

如此处所示,CarFactory看起来是确定性的。但是,很难说出来,因为没有显示整个实现。但是,如果它是referentially transparent,那为什么还要初始化呢?

难道仅仅是静态功能吗?

public static class CarFactory
{
    public static ICar CreateInstance(string carName)
    {
        // choose type of class from all classes that implement ICar 
        Type t = GetTypeToCreate(carName); 

        return Activator.CreateInstance(t) as ICar;
    }

    // some more code...
}