依赖注入 - 在类中创建实例是一个好主意吗?

时间:2012-11-21 16:41:22

标签: language-agnostic dependency-injection

自从我了解了依赖注入之后,我很难决定是否应该在类中注入或创建某些内容。

考虑以下不使用DI的示例:

class Car
{
    private Wheels _wheels;
    private Chasis _chasis;
    private Fuel _fuel;

    public Car()
    {
        _wheels = new Wheels();
        _chasis = new Chasis();
        _fuel = new Fuel();
    }

    public ExhaustGas Exhaust
    {
        get
        {
            return new ExhaustGas();
        }
    }
}

这些在汽车内部创建的实例会注入什么?如果是这样,您如何决定?

这是我的推理:

  • 燃料 - 由于燃料是从外部来源获得的,我肯定可以看到燃料改变的原因,我会给它添加抽象(IFuel)并注入它。
  • 车轮 - 即使车轮是汽车的一部分,您也可以轻松更换车轮。所以我说它也应该注入。
  • Chasis - 这个需要更多考虑。底盘是汽车中非常重要的一部分,因此将其作为外部依赖似乎有点奇怪。但是,您当然可以单独在Chasis上运行测试,并且可以使用假人测试汽车(即使我不确定它是否应该)。是否应注入物体的这一重要部分?
  • ExhaustGas - 这个更难。我可以注入一个按需创建IExhaustGas的工厂,但我不确定是否应该。我不应该将此实例作为工厂注入,因为它是按需创建的吗?如果没有,在这种情况下我的推理应该是什么?

我很想听听你对我在这里提出的变量的看法,以及关于你如何决定什么时候注射东西以及什么时候不做的更通用的推理。

1 个答案:

答案 0 :(得分:2)

根据经验,应注入所有外部依赖项。原因很简单:您希望能够模拟依赖项进行测试,并且可以在必要时灵活地替换它们。

为了应对注入一切的复杂性,有几种策略。如果您只想注入一些东西,请将其设为可选:

class Foo {

    private _bar
    private _baz

    public Foo(Bar bar = null, Baz baz = null) {
        if (!bar)  bar = new Bar;
        if (!baz)  baz = new Baz;

        _bar = bar
        _baz = baz
    }

}

这仍然具有依赖注入的所有优点,同时避免必要的实例化疯狂。

或者,使用像CarDependencyFactory这样的工厂,它可以在一个类中实例化所有必需的依赖项。也可以选择另外选择。

依赖注入容器/管理器/框架也可以提供帮助。最重要的是,您应该注入所有内容,除非您确实确定依赖项永远不需要替换,并且可以一段代码添加到另一个。

另见How Not To Kill Your Testability Using Statics