代码之家  ›  专栏  ›  技术社区  ›  Mateusz Krzaczek

对于密封类,有没有比抽象工厂更简单的替代方法?

  •  2
  • Mateusz Krzaczek  · 技术社区  · 7 年前

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

    在我的示例中,我有一个类:

    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 不实现任何接口,永远不会被另一个类替换。因此,这个工厂只不过是一段无用的代码。它可以完全省略,以支持 AssetsDownloadingProcessFactory 构造函数。然而,我不能使用依赖注入到构造函数。

    我想从我的IoC容器中使用注入的好处,而不需要创建工厂和创建无用的代码。正确的方法是什么?我是否遗漏了什么或使用DI有误?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Steven    6 年前

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

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

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

    当在对象图构造期间未使用运行时数据时,可以在组合根内使用DI创建组件,因此问题就不会出现。

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

    因为对象组合应该只在应用程序的 Composition Root 然而,这意味着你的抽象工厂 必须是 抽象。只有这样,你才能防止你的建筑 AssetsDownloadingProcess 组件发生在合成根内。

    方法是:

    1. 定义抽象,即。 IAssetsDownloadingProcessFactory 在该工厂消费者居住的应用层。
    2. 创建此抽象的实现 在…内 组成根。

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