这两种模式看起来像是控制反转原理的实现。也就是说,一个对象不应该知道如何构造它的依赖。
依赖注入(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 Container一个坏名字吗?是IOC / DI容器只是另一种类型的服务定位器?是我们使用DI容器主要是当我们有很多依赖的事实的细微差别吗?
差别可能看起来很小,但即使使用ServiceLocator,该类仍然负责创建其依赖关系。它只是使用服务定位器来做到这一点。使用DI,类被赋予它的依赖。它既不知道,也不在乎他们来自哪里。这样做的一个重要结果是,DI示例更容易进行单元测试 – 因为您可以传递其依赖对象的模拟实现。你可以结合两个 – 并注入服务定位器(或工厂),如果你想。