2011-06-09 127 views
5

我审查代码具有很多语句的是这样的:服务定位与依赖注入

private SomeInterface x = Locator.getInstance(SomeInterface.class) 

我希望像

private SomeInterface x; 

@Inject 
public Consumer(SomeInterface x){ // constructor 
    this.x = x; 
} 

有什么问题与第一种方法?好的,依赖关系并不那么明显,但实现可以通过配置Locator轻松地进行交换。

+0

https://steveschols.wordpress.com/2012/05/14/dependency-injection-vs-service-locator/#comment-539 – 2016-06-15 12:57:23

回答

6

第一个例子: X = Locator.getInstance(SomeInterface.class)是看起来像Service Locator模式,并http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx检查这篇文章中说,服务定位器是一个反模式,应该避免

而为第二次使用它的所有罚款我喜欢构造函数注入,其顺利罚款实施。但我想不使用Attributes(Java中的annotanitons?)导致任何时候我可能想更改我正在使用的DI容器,我不想从所有类中删除属性。

+2

'@ Inject'已标准化Java [JSR-330](http://www.jcp.org/en/jsr/detail?id=330) – deamon 2011-06-09 11:42:39

+0

@deamon我认为这只是CrazyBob的DI的注释。不知道它被接受为语言标准。谢谢(你的)信息。 – adt 2011-06-09 12:32:11

9

Martin Fowler的写了article on DI versus Locators

对于DI:

  • 更轻松地确定相关性的组件已 - 看 构造。
  • 组件不依赖于服务定位器,因此如果组件与 使用不同的框架,则不存在 问题。
  • DI可以使测试更加简单,但良好的服务定位器机制将 化妆磕碰同样可行

反对DI:

  • 难以调试和理解。
  • 一旦配置了 ,组件就无法从喷油器请求额外的服务。

我个人不认为有什么本质坏的第一定位器为基础的方法 - 我想,虽然不DI规范这一点,所以如果它是可用的,我会用它。所有好的想法往往最终都会在某个时候成为框架,所以这里就发生了一些事情。加上DI,您可以利用其他注释,范围等,而无需推出自己的代码。而且你的项目使用更好的IMO代码越少。我会留下最后一句话福勒虽然:

服务定位和 依赖注入之间的选择比从应用程序中使用 服务分离 服务配置的原则不太重要 。

1

没有什么“错误”这样的服务定位器模式,

在这种特殊情况下,有利于DI的一个主要理由是可测性。

毫无疑问,DI允许更好的单元测试。 Locator上的静态getInstance方法使得单独测试更加困难。

+0

除了单元测试,还有更多。 Mark Seemann已经非常清楚地描述了这一点:http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx。 – Steven 2011-06-09 11:50:51

+2

想要避免这些类型的哲学讨论:)“反模式”是一个过度使用的声明恕我直言。我个人也赞成DI,但在代码审查期间我不会将其标记为反模式。 – ddewaele 2011-06-09 11:59:37

+0

几年前,我在项目中引入了IoC(以服务定位器模式的形式),以允许该团队开始编写测试。这是一个从根本上无法测试的好开始。但是现在,超过两年后,将这种模式遍布全球而不是使用直接投资是一个真正的痛苦。所以对我来说这不是哲学了。我去过那里,我经历过,这都是我的错。现在,我尽可能地尖叫,以帮助别人解决我犯的错误。 – Steven 2011-06-09 12:27:57

2

Service locator模式使用称为“服务定位器”的中央注册表,根据请求返回执行特定任务所需的信息。

这些服务定位器设计模式中最糟糕的方面:

  • 东西放置在注册表中与 关于该系统的其余部分有效黑匣子。这使得难以检测并且从其错误中恢复,并且可能使得整个系统不太可靠。

  • 注册表必须是唯一的,这可能会使其成为并行应用程序的
    的瓶颈。

  • 注册表可能是一个严重的安全漏洞,因为它允许外部人员直接向应用程序注入代码。

  • 无法通过构造函数传递依赖和硬(如我们在DI模式做)到单元测试

我使用服务定位器设计模式,我认为是可以接受的只是对顶层您应用程序时,您的服务定位器可能不会更改