对于密封类,是否有更简单的抽象工厂替代方案?

时间:2017-11-16 16:29:33

标签: dependency-injection inversion-of-control ioc-container

基于this问题,使用ioc-container时使用运行时参数初始化新对象的方法是创建抽象工厂。

在我的例子中,我有这个课程:

TcAdsClient.WriteAny( ixGroup, ixOffset, data )

建造它的工厂:

internal sealed class AssetsDownloadingProcess
{
    private readonly IBackgroundWorker _backgroundWorker;
    private readonly IAssetsStorage _assetsStorage;
    private readonly Parameters _parameters;

    public AssetsDownloadingProcess(IBackgroundWorker backgroundWorker, 
        IAssetsStorage assetsStorage, Parameters parameters)
    {
        _parameters = parameters.Clone();

        _backgroundWorker = backgroundWorker;
        _assetsStorage = assetsStorage;
    }
}

如您所见,internal sealed class AssetsDownloadingProcessFactory { private readonly IBackgroundWorker _backgroundWorker; private readonly IAssetsStorage _assetsStorage; public AssetsDownloadingProcessFactory(IBackgroundWorker backgroundWorker, IAssetsStorage assetsStorage) { _backgroundWorker = backgroundWorker; _assetsStorage = assetsStorage; } public AssetsDownloadingProcess CreateProcess( AssetsDownloadingProcess.Parameters parameters) { return new AssetsDownloadingProcess( _backgroundWorker, _assetsStorage, parameters); } } 未实现任何接口,永远不会被其他类替换。因此这个工厂只不过是无用的一段代码。它可以完全省略,有利于AssetsDownloadingProcess构造函数。但是,我不能将依赖注入用于构造函数。

我想从IoC容器中使用Injection的好处,而无需创建工厂和创建无用代码的麻烦。这样做的正确方法是什么?我错过了什么或使用DI错误了吗?

1 个答案:

答案 0 :(得分:1)

通常,您应该阻止使用运行时数据来创建和初始化应用程序组件,如here所述。通过构造函数传递运行时数据这一事实迫使您创建工厂。

the article给出的将运行时数据注入组件的问题的解决方案是让运行时数据通过以下任一方式在初始化对象图上通过方法调用流动:

  • 通过API的方法调用传递运行时数据,或
  • 从允许解析运行时数据的特定抽象中检索运行时数据。

在对象图构造过程中未使用运行时数据时,可以使用组合根中的DI创建组件,因此您的问题就会消失。

然而,这样做并不总是可行的,当它不是时,抽象工厂就是解决方案。

因为对象组合应仅在应用程序Composition Root中进行,这意味着您的抽象工厂必须抽象。只有这样才能防止AssetsDownloadingProcess组件的构造发生在组合根目录中。

这样做的方法是:

  1. 定义一个抽象,即在该工厂的消费者居住的应用层中IAssetsDownloadingProcessFactory
  2. 在< - >组合根
  3. 中创建此抽象的实现。

    不使用抽象意味着消费者将依赖于具体的AssetsDownloadingProcessFactory类(这是Dependency Inversion Principle violation),并将对象组合拉出组合根。这将导致对象组合分散在整个应用程序中,这会妨碍可维护性。