引用的大多数使用依赖注入的例子,我们也可以使用工厂模式来解决。看起来当涉及到使用/设计时,依赖注入和工厂之间的区别是模糊或稀薄的。

曾经有人告诉我,你如何使用它才会有所不同!

我曾经使用StructureMap一个DI容器来解决一个问题,后来我重新设计了它来使用一个简单的工厂,并删除了对StructureMap的引用。

谁能告诉我它们之间的区别在哪里使用什么,这里的最佳实践是什么?


当前回答

这里的大多数答案都解释了两者的概念差异和实现细节。但是我无法解释在应用上的差异,IMO是最重要的,OP问的是什么。所以让我重新讨论这个话题……

曾经有人告诉我,你如何使用它才会有所不同!

完全正确。在90%的情况下,你可以使用Factory或DI来获取对象引用,通常你最终会使用后者。在另外10%的情况下,使用Factory是唯一正确的方法。这些情况包括通过运行时参数的变量获取对象。是这样的:

IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com",
        useCookies: false, connectionTimeout: 120);

在这种情况下,从DI获取客户端是不可能的(或者至少需要一些丑陋的解决方案)。因此,作为决策的一般规则:如果可以在没有任何运行时计算参数的情况下获得依赖项,则首选DI,否则使用Factory。

其他回答

这里的大多数答案都解释了两者的概念差异和实现细节。但是我无法解释在应用上的差异,IMO是最重要的,OP问的是什么。所以让我重新讨论这个话题……

曾经有人告诉我,你如何使用它才会有所不同!

完全正确。在90%的情况下,你可以使用Factory或DI来获取对象引用,通常你最终会使用后者。在另外10%的情况下,使用Factory是唯一正确的方法。这些情况包括通过运行时参数的变量获取对象。是这样的:

IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com",
        useCookies: false, connectionTimeout: 120);

在这种情况下,从DI获取客户端是不可能的(或者至少需要一些丑陋的解决方案)。因此,作为决策的一般规则:如果可以在没有任何运行时计算参数的情况下获得依赖项,则首选DI,否则使用Factory。

当我读到关于DI的文章时,我也有同样的问题。 最后,这就是我所理解的,但如果我错了,请纠正我。

“很久以前,有一些小国,它们有自己的管理机构,根据自己的成文规则进行控制和决策。后来形成了一个大政府,消除了所有这些小的管理机构,这些机构只有一套规则(宪法),并通过法院执行。”

小王国的管理机构是“工厂”

大政府是“依赖注入器”。

我相信DI是工厂的一种抽象层,但是它们还提供了抽象之外的好处。真正的工厂知道如何实例化单一类型并配置它。好的DI层通过配置提供实例化和配置多种类型的能力。

显然,对于具有一些简单类型的项目(在其构造中需要相对稳定的业务逻辑),工厂模式易于理解、实现并且工作良好。

OTOH,如果您有一个包含许多类型的项目,您希望经常更改这些类型的实现,DI通过其配置为您提供了在运行时执行此操作的灵活性,而无需重新编译工厂。

我使用这两种方法来创建反转控制策略,为在我之后需要维护它的开发人员提供了更强的可读性。

我使用工厂来创建不同的层对象(业务,数据访问)。

ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness();

另一个开发人员会看到这一点,当创建业务层对象时,他会在BusinessFactory中查看,智能感知会为开发人员提供所有可能创建的业务层。不需要玩游戏,找到我想要创建的界面。

这个结构已经是控制反转了。我不再负责创建特定的对象。但是您仍然需要确保依赖注入能够轻松地更改内容。 创建自己的自定义依赖注入是荒谬的,所以我使用Unity。在CreateCarBusiness()中,我要求Unity解决哪个类属于这个和它的生命周期。

所以我的代码工厂依赖注入结构是:

public static class BusinessFactory
{
    public static ICarBusiness CreateCarBusiness()
    {
       return Container.Resolve<ICarBusiness>();
    }
}

现在我两者兼得。我的代码对于其他开发人员来说也更易于阅读,因为我使用的对象的范围,而不是构造函数依赖注入,它只是说在创建类时每个对象都是可用的。

当我创建单元测试时,我使用它将我的数据库数据访问更改为自定义编码的数据访问层。我不希望我的单元测试与数据库、网络服务器、电子邮件服务器等通信。他们需要测试我的业务层,因为这是智能所在。

比诺,

我不认为你必须选择其中一个而不是另一个。

将依赖类或接口移动到类构造函数或setter的行为遵循DI模式。传递给构造函数或集合的对象可以用Factory实现。

什么时候使用?使用开发人员擅长的模式。他们觉得什么最舒服,什么最容易理解。