What's the difference between the Dependency Injection and Service Locator patterns?

Both patterns seem like an implementation of the principle of inversion of control. That is, that an object should not know how to construct its dependencies.

Dependency Injection (DI) seems to use a constructor or setter to "inject" it's dependencies.

Example of using Constructor Injection:

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

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

  //...
}

Service Locator seems to use a "container", which wires up its dependencies and gives foo it's bar.

Example of using a Service Locator:

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

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

  //...
}

Because our dependencies are just objects themselves, these dependencies have dependencies, which have even more dependencies, and so on and so forth. Thus, the Inversion of Control Container (or DI Container) was born. Examples: Castle Windsor, Ninject, Structure Map, Spring, etc.)

But a IOC/DI Container looks exactly like a Service Locator. Is calling it a DI Container a bad name? Is an IOC/DI Container just another type of Service Locator? Is the nuance in the fact that we use DI Containers mostly when we have many Dependencies?


The difference may seem slight, but even with the ServiceLocator, the class is still responsible for creating its dependencies. It just uses the service locator to do it. With DI, the class is given it's dependencies. It neither knows, nor cares where they come from. One important result of this is that the DI example is much easier to unit test -- because you can pass it mock implementations of its dependent objects. You could combine the two -- and inject the service locator (or a factory), if you wanted.


When you use a service locator, every class will have a dependency on your service locator. This is not the case with dependency injection. The dependency injector will typically be called only once at startup to inject dependencies into some main class. The classes this main class depends on will recursively have their dependencies injected, until you have a complete object graph.

A good comparison: http://martinfowler.com/articles/injection.html

If your dependency injector looks like a service locator, where the classes call the injector directly, it is probably not a dependency injector, but rather a service locator.


Service locators hide dependencies - you can't tell by looking at an object whether it hits a database or not (for example) when it obtains connections from a locator. With dependency injection (at least constructor injection) the dependencies are explicit.

Moreover, service locators break encapsulation because they provide a global point of access to dependencies of other objects. With service locator, as with any singleton:

it becomes difficult to specify the pre and post conditions for the client object's interface, because the workings of its implementation can be meddled with from outside.

With dependency injection, once an object's dependencies are specified, they are under control of the object itself.

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

上一篇: 在Angular.js中可以注入什么“东西”?

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