题
依赖注入似乎是一件好事。一般来说,依赖项应该注入到需要它们的方法中,还是应该注入到类的构造函数中?
请参阅下面的示例来演示注入相同依赖项的两种方法。
//Inject the dependency into the methods that require ImportantClass
Class Something {
public Something()
{
//empty
}
public void A()
{
//do something without x
}
public void B(ImportantClass x)
{
//do something with x
}
public void C(ImportantClass x)
{
//do something with x
}
}
//Inject the dependency into the constructor once
Class Something {
private ImportantClass _x
public Something(ImportantClass x)
{
this._x = x;
}
public void A()
{
//do something without x
}
public void B()
{
//do something with this._x
}
public void C()
{
//do something with this._x
}
}
解决方案
构造函数注入的主要好处是它允许您的字段被标记为最终的。例如:
class Foo {
private final Bar _bar;
Foo(Bar bar) {
_bar=bar;
}
}
以下页面列出了优点和缺点: 吉斯最佳实践:
方法注入
- + 不是字段注入
- + 唯一适用于一些奇怪的边缘情况
构造函数注入
- + 字段可以是最终的!
- + 不可能跳过注射
- + 依赖关系一目了然
- + 这就是建筑理念的全部内容
- - 无可选注射
- - 当 DI 库无法自行实例化时无用
- - 子类需要“了解”其超类所需的注入
- - 对于只“关心”其中一个参数的测试不太方便
其他提示
通过不在每个方法中注入依赖项,然后强制每个调用者知道或检索依赖项。
同样从工具的角度来看,有许多框架可用(至少在.NET中),使得构造函数注入更容易实现。这不应该影响决定,但会使其更具吸引力。
祝你好运。如果您在方法期间注入,则不会将行为抽象与具体依赖项区分开来。这是一个很大的没有没有:)。您希望依赖于抽象,因此您不会依赖于类依赖项的依赖项。 。 。
由于您的构造函数不会出现在您的具体类支持的任何接口中,而不是您没有耦合到该依赖项。但方法调用会有这个问题。
这是一篇关于这个问题的好文章:
http:// chrisdonnan.com/blog/2007/05/20/conquest-through-extreme-composition-glue-part-2/
另一种方法是为依赖项用户设置setter。有时这与构造函数注入相结合。如果您想要更改以后使用的实现而无需重新创建实例,这将非常有用。
public interface IFoo
{
void Do();
}
public class DefaultFoo : IFoo
{
public void Do()
{
}
}
public class UsesFoo
{
private IFoo foo;
public IFoo Foo
{
set { this.foo = value; }
}
public UsesFoo()
{
this.Foo = new DefaultFoo();
}
public UsesFoo( IFoo foo )
{
this.Foo = foo;
}
public void DoFoo()
{
this.Foo.Do();
}
}
Crazy Bob Lee 说尽可能使用构造函数注入。当您无法控制实例化时(例如在servlet中),仅使用方法注入。
不隶属于 StackOverflow