【发布时间】:2016-02-10 20:50:42
【问题描述】:
许多 IoC 容器都具有“自动工厂”的功能,可根据其接口生成抽象工厂的实现。然而,它通常是二等公民:StructureMap declares only a basic support 用于该功能,而 Simple Injector 的作者故意从库中省略自动工厂,声称 when applying Dependency Injection correctly, the need for using factories is minimized。这不是我遇到类似观点的唯一地方。
然而,在我看来,在使用 IoC 和编写领域模型时,工厂似乎是设计中不可或缺的元素。比如说,一个简单的虚构示例可能是:
class Order
{
private ITaxProvider _taxProvider;
public decimal Quantity { get; set; }
public decimal PricePerUnit { get; set; }
public decimal Cost { get; set; }
public Order(ITaxProvider taxProvider)
{
_taxProvider = taxProvider;
}
public decimal GetProfit()
{
// Don't nitpick on this example, please, it's just to show some
// kind of domain object that depends on some kind of service,
// but also has some logic of its own.
decimal grossProfit = Quantity * PricePerUnit - Cost;
decimal netProfit = grossProfit * (1.0m - _taxProvider.GetTaxRate());
return netProfit;
}
}
在这种情况下,每次我创建一个Order,比如说,在 MVC 控制器中,我都需要使用一个工厂。最终,这很可能对任何域对象都是正确的。即使它们现在可能没有任何依赖关系,也很可能有人在某些时候会要求某些功能根据配置值表现不同,或者某些代码将被重构为单独的类,然后可能会被解耦使用 DI 可在分离中进行测试。
所以我几乎愿意推出工厂来控制每个域对象的初始化。但比我更有经验的开发人员说我不应该经常将工厂与 IoC 容器一起使用。我应该对我的代码设计进行哪些更改以使工厂变得不必要?
【问题讨论】:
-
要了解 Steven 将工厂排除在 Simple Injector 之外的原因,您应该从头开始:here
-
该参数反对返回其他组件的工厂,而不反对任何类型的工厂,例如返回域对象或其他值类型的工厂。退回组件的工厂尤其是容器的“自动工厂”功能提供的工厂类型。
-
那么您的 TaxProvider 就是这里的工厂?从这个意义上说,存储库也是工厂。他们没有任何问题。
-
@Steven 不,我没有展示工厂,工厂将用于创建
Order的实例。ITaxProvider是由 IoC 容器提供的依赖项。这就是需要工厂的原因。 -
允许创建实体的抽象不称为工厂;这是一个存储库。但是,您犯的错误是您在实体构造函数中注入了组件。这被认为是不好的。您的 IoC 容器不应负责创建实体;它的工作是构建组件。
标签: design-patterns dependency-injection inversion-of-control ioc-container simple-injector