我正在审查代码中有很多这样的陈述:
private SomeInterface x = Locator.getInstance(SomeInterface.class)
我希望像
这样的东西private SomeInterface x;
@Inject
public Consumer(SomeInterface x){ // constructor
this.x = x;
}
第一种方法有问题吗?好的,依赖关系并不那么明显,但可以通过配置Locator轻松交换实现。
答案 0 :(得分:10)
Martin Fowler写了article on DI versus Locators:
对于DI:
- 更容易确定组件具有哪些依赖关系 - 请注意 构造
- 组件不依赖于服务定位器,因此没有 如果组件使用的问题 一个不同的框架。
- DI可以使测试更容易,但是一个好的服务定位器机制会 使存根同样可行
反对DI:
- 难以调试和理解。
- 组件无法从注入器请求额外服务 已配置。
我个人认为第一个基于定位器的方法没有任何本质上的错误 - 我想DI确实标准化了,所以如果它可用我将使用它。所有好的想法往往最终都会成为框架,所以这就是这里发生的事情。使用DI,您可以利用其他注释,范围等,而无需滚动自己的代码。而且您的项目使用的定制代码越少,IMO越好。我会把最后一句话留给福勒:
服务定位器和服务定位器之间的选择 依赖注入不太重要 而不是分离的原则 服务配置从使用 应用程序中的服务。
答案 1 :(得分:6)
第一个例子: x = Locator.getInstance(SomeInterface.class)看起来像Service Locator模式,而http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx检查这篇文章它说服务定位器是反模式的,应该避免
对于第二次使用它的一切都很好,我喜欢构造函数注入,它的顺利实现。但我想不使用属性(Java中的annotanitons?)因为任何时候我可能想要更改我正在使用的DI容器,我不想从所有类中删除属性。
答案 2 :(得分:2)
Service locator模式使用称为“服务定位器”的中央注册表,根据请求返回执行特定任务所需的信息。
这是服务定位器设计模式最糟糕的一面:
放在注册表中的东西实际上是黑盒子 关于系统的其余部分。这使得检测和检测变得更加困难 从他们的错误中恢复,并可能使整个系统更少 可靠。
注册表必须是唯一的,这可能使其成为
的瓶颈
并发申请。
注册表可能是一个严重的安全漏洞,因为它 允许外人将代码注入到应用程序中。
无法通过构造函数传递依赖项(就像我们在DI模式中那样)并且难以进行单元测试
我认为使用服务定位器设计模式只有在您的服务定位器可能不会更改时才能在应用程序的顶层接受
答案 3 :(得分:1)
服务定位器模式没有“错误”,
在这种特殊情况下,支持DI的一个主要论点是可测试性。
毫无疑问,DI允许更好的单元测试。 Locator上的静态getInstance方法使得单独测试变得更加困难。