依赖注入和服务定位器模式有什么区别?

这两种模式似乎都是控制反转原理的实现。 也就是说,一个对象不应该知道如何构建它的依赖关系。

依赖注入(DI)似乎使用构造函数或setter来“注入”它的依赖关系。

使用构造函数注入的示例:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

服务定位器似乎使用一个“容器”,它连接它的依赖关系,并赋予foo它的阻碍。

使用服务定位器的示例:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo()
  {
    this.bar = Container.Get<IBar>();
  }

  //...
}

因为我们的依赖关系本身就是对象,所以这些依赖关系具有依赖关系,依赖关系甚至更多,依此类推。 因此,控制容器反转(或称DI容器)诞生了。 例如:Castle Windsor,Ninject,Structure Map,Spring等)

但IOC / DI容器看起来完全像服务定位器。 称它为DI容器是一个坏名字? IOC / DI容器是另一种类型的服务定位器吗? 我们使用DI容器的主要原因是我们有很多依赖关系吗?


差别可能看起来很小,但即使使用ServiceLocator,该类仍负责创建其依赖关系。 它只是使用服务定位器来做到这一点。 使用DI,该类将被赋予它的依赖关系。 它既不知道,也不在乎它们来自哪里。 这样做的一个重要结果是,DI示例更容易进行单元测试 - 因为您可以传递它的依赖对象的模拟实现。 你可以将两者结合起来 - 如果你想的话,注入服务定位器(或工厂)。


当您使用服务定位器时,每个类都将依赖于您的服务定位器。 依赖注入不是这种情况。 在启动时,依赖注入器通常只会被调用一次,以将依赖注入到某个主类中。 这个主类依赖的类将递归地注入它们的依赖关系,直到你有一个完整的对象图。

一个很好的比较:http://martinfowler.com/articles/injection.html

如果您的依赖注入器看起来像服务定位器,这些类直接调用注入器,那么它可能不是依赖注入器,而是服务定位器。


服务定位器隐藏依赖关系 - 当你从一个定位器获得连接时,你无法通过查看一个对象来判断它是否碰到数据库(例如)。 使用依赖注入(至少是构造函数注入),依赖是明确的。

而且,服务定位器破坏了封装,因为它们提供了访问其他对象依赖关系的全局点。 有了服务定位器,就像任何单身人士一样:

要为客户端对象的接口指定前置和后置条件变得困难,因为其实现的工作可以从外部进行。

通过依赖注入,一旦指定了对象的依赖关系,它们就受到对象本身的控制。

链接地址: http://www.djcxy.com/p/77787.html

上一篇: What's the difference between the Dependency Injection and Service Locator patterns?

下一篇: Confused with SOLID and Dependecy Injection