依赖注入与抽象工厂 - 选择正确的模式

时间:2017-05-25 20:37:17

标签: c# design-patterns dependency-injection interface abstract-factory

我正在开发将问题从旧问题迁移到新问题跟踪系统的工具。我已将所有内容与界面分开,但我不确定将它粘合在一起的最佳方法是什么。我有3个依赖项,需要运行时数据:

  • INewSystemClient - 连接到新系统的客户端
  • IRetryStrategy - 处理超时和重试
  • IMigrationSettings

这3个依赖项是许多其他依赖项的依赖项。我无法找出粘合所有内容的其他方法,而不是将这3个作为单例注册(通过DI容器)。我也知道,单身人士被认为是一种糟糕的模式,所以我考虑转向抽象工厂。

迫使我使用单身人士的示例关系:

  • Dependency1(INewSystemClient client,...)// Dependency1的构造函数
  • Dependency2(INewSystemClient client,...)// Dependency2的构造函数

INewSystemClient需要运行时数据,如user,pw,host等。

我应该切换到抽象工厂并使工厂创建对象而不是DI容器吗?

2 个答案:

答案 0 :(得分:1)

我认为你混淆的术语就像Singleton pattern(大多数人说它现在是反模式)与你的IOC中的单身实例不同,Abstract factory pattern不一样DI工厂。您需要考虑的是scopes或创建和处置对象时。

在桌面应用程序中,可以有多个范围,您可以在其中注册对象(在应用程序级别或“单个”,在模块级别,在线程级别,在页面级别...)取决于你正在使用的框架(Prism,MvvmLight,caliburn.micro ...)如果你正在构建自己的系统,你可能想看看其他一些框架是如何做到的。 我知道Unity有一种处理factorieslazy初始化的很酷的方法。

通常,单例实例最适合用于不会在多个线程中访问的内容,这些内容将更改某些值。这是当你需要创建锁时,你可以通过阻止你的UI线程来减慢速度。例如,如果你有一个只调用一个后端api的HttpClient,每个人都可以使用它,那么将它作为一个单例范围是有意义的。

例如,如果您想要写入数据库,则可能希望每页具有不同的EF上下文,因此实体跟踪不会发生在两页上。

答案 1 :(得分:1)

  

我有3个依赖项,需要运行时数据:

从您的问题不清楚这些依赖关系如何消耗运行时数据。如果他们在初始化期间需要它,那就是a code smell。如果您通过已初始化(和不可变)类的方法调用传递运行时数据,那就完全没问题了。

  

我也知道,单身人士被认为是一种糟糕的模式,所以我正在考虑转向抽象工厂。

Filip Cordas已经触及了这一点,但我想重复一遍:你让两件事感到困惑。在应用DI时, Singleton Pattern 是一件坏事,但在运行时(a.k.a. Singleton Lifestyle )拥有一个类的单个实例是完全没问题的。有些人(像我一样)更喜欢将所有组件注册到 Singleton Lifestyle ,因为这会强制不变性和无状态,这简化了注册并防止了各种常见的错误配置,例如为Captive Dependencies

  

我应该切换到抽象工厂并使工厂创建对象而不是DI容器吗?

正如here所解释的那样,抽象工厂通常不是正确的解决方案,我认为它们是代码味道。它们通常用于使用运行时数据构建应用程序组件,但如前所述,应用程序组件在构造期间不应要求运行时数据。