【问题标题】:Factory vs PicoContainer - Benefits of IoC ContainersFactory vs PicoContainer - IoC 容器的好处
【发布时间】:2011-09-06 22:42:03
【问题描述】:

我正试图为花哨的 IoC 原则敞开心扉,我偶然发现了这篇文章: Martin fowler on IoC

他提供了一些使用PicoContainer的例子:

private MutablePicoContainer configureContainer() {
        MutablePicoContainer pico = new DefaultPicoContainer();
        Parameter[] finderParams =  {new ConstantParameter("movies1.txt")};
        pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams);
        pico.registerComponentImplementation(MovieLister.class);
        return pico;
    }

然后是示例用法:

public void testWithPico() {
        MutablePicoContainer pico = configureContainer();
        MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);
        Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
        assertEquals("Once Upon a Time in the West", movies[0].getTitle());
    }

首先想到的是:为什么要使用像 PicoContainer 这样复杂的东西来配置对象的创建 - 实际上应用依赖注入 - (我是 .NET 开发人员,所以在 .NET 中可能需要使用 Reflection,这很耗时),当我们可以在(例如)FactoriesBuilder 中实现对象创建的相同封装时,使用快速 new 运算符。

另一件事:configureContainer() 仍在编译,确切的类型在编译时指定。那么为什么不使用工厂,并在配置文件中决定使用哪个工厂呢?

由于我是这种方法的新手,我想在 IoC 容器的好处方面我缺少一些东西。

【问题讨论】:

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


    【解决方案1】:

    我刚刚更新了与此问题here 相关的答案。

    在 .Net 中,我会查看有关 Unity Framework 的文档(来自 MSFT)。我也对硬编码实现注册的想法持怀疑态度,但随着时间的推移,我克服了它。主要是因为您确实可以使用基于文件的配置,您可以注册多个实现(并标记每个实现,以便可以调用它们)并且通常无论如何您不会在生产中使用多个实现。

    最大的好处是自动装配 - 可以为您找到依赖项。一组复杂的类的链式自动装配非常漂亮,如果没有别的,因为您可以轻松地注册 10 个有问题的类之一的 Mock 实例,而无需触及实现代码。这以引导容器为代价导致了大量的可测试性。这些天对我来说,这是赌注,甚至不值得讨论。想象一下,如果 Type1 取决于 2、3 和 4,4 取决于 5 和 6,6 取决于 7。如果我想测试系统如何对 6 中的错误做出反应,我该怎么做?我需要做的就是模拟(使用像 Moq 这样很酷的框架)Type6,注册模拟,但对其他类使用真实的实现。

    [Fact]
    public void TestType6BlowingUp()
    {
      IocContainer container = new IocContainer();
      container.RegisterType(Type1, Type1Impl);
      container.RegisterType(Type2, Type2Impl);
      container.RegisterType(Type3, Type3Impl);
      container.RegisterType(Type4, Type4Impl);
      container.RegisterType(Type5, Type5Impl);
      container.RegisterType(Type6, Type6Mock);
      container.RegisterType(Type7, Type7Impl);
    
      Type1 type1 = container.Resolve<Type1>();
      Type1Response response = type1.DoSomethingThatCallsType6Downstream();
      //Should get errorcode 500
      Assert.True("Expected ErrorCode 500", response.ErrorCode == 500);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-22
      • 2017-09-25
      • 1970-01-01
      • 2014-04-29
      • 1970-01-01
      • 2011-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多