简体   繁体   中英

Service Locator vs. Dependency Injection

I'm reviewing code with a lot of statements like this:

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

I would expect something like

private SomeInterface x;

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

Is there something wrong with the first approach? Ok, dependencies are not so obvious, but implementations could easily be swapped through configuration of Locator.

Martin Fowler wrote an article on DI versus Locators :

For DI:

  • Easier to determine what dependencies a component has - look at constructor.
  • Component does not have dependency on Service Locator so there is not a problem if the component is used with a different framework.
  • DI may make testing easier but a good Service Locator mechanism will make stubbing equally feasible

Against DI:

  • Harder to debug and understand.
  • Component cannot request extra services from injector once it had been configured.

I personally don't think there's anything inherently bad with the first locator based approach - I guess DI does standardise this though, so if it's available I would use it. All good ideas tend to end up as frameworks at some point, so this has what's happened here. Plus with DI you can take advantage of other annotations, scopes, etc. without having to roll your own code. And the less bespoke code your project uses the better IMO. I'll leave the last word to Fowler though:

The choice between Service Locator and Dependency Injection is less important than the principle of separating service configuration from the use of services within an application.

First example: x = Locator.getInstance(SomeInterface.class) is looks like Service Locator pattern, and http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx check this article it says Service Locator is an anti-pattern and should be avoided

And for the second usage its all fine i like Constructor Injection, its smooth fine implementation. But I would like to not to use Attributes ( annotanitons in Java?) cause anytime i might want to change DI container i am using and i dont want to remove an attribute from all classes.

Service locator pattern uses a central registry known as the "service locator" which on request returns the information necessary to perform a certain task.

These are the worst sides of Service Locator Design Pattern:

  • Things placed in the registry are effectively black boxes with regards to the rest of the system. This makes it harder to detect and recover from their errors, and may make the system as a whole less reliable.

  • The registry must be unique, which can make it a bottleneck for
    concurrent applications.

  • The registry can be a serious security vulnerability, because it allows outsiders to inject code right into an application.

  • Can't pass dependencies by constructor (as we do in DI pattern) and hard to unit-test

And I my opinion using service locator design pattern is acceptable only on top level of your application when your service locator probably will not change

There's nothing "wrong" as such with the service locator pattern,

In this particular case, the one major argument in favor of DI would be testability.

Without a doubt, DI allows for better unit testing. The static getInstance method on Locator makes it more difficult to test in isolation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM