I read an article focused mainly on Dependency Injection. However, what interested me even more was it's discussion around Service Locator as an alternative to DI. In my opinion, Service Locator should only be considered as an alternative in some scenarios. However, before I blog my opinions about Service Locator and Dependency Injection, I'm going to start by talking about each one individually. I don't want to assume everyone reading this knows what both patterns are and really don't want to write one giant post. So, read below for a summary of dependency injection or visit the article mentioned above for more detail.
Quick Explanation
First of all, you may have been doing DI without knowing what it was. But, to explain, Dependency Injection is exactly what it sounds like. A class's dependencies are injected into the class rather than created inside it. Probably best explained with an example.
Instead of:
class RequestHandler {
private ResponseGenerator responseGenerator;
public RequestHandler() {
this.responseGenerator = new ResponseGeneratorImpl();
}
}
Do this:
class RequestHandler {
private ResponseGenerator responseGenerator;
public RequestHandler(ResponseGenerator responseGenerator) {
this.responseGenerator = responseGenerator;
}
}
So, what does this do? We've accomplished two things. First we've created loose coupling between RequestHandler and ResponseGenerator. The first method uses a specific implementation while the second doesn't. Second, we've given control to the entity instantiating RequestHandler. This says, "I don't want to limit you to a specific implementation of ResponseGenerator, so i'll give you control and allow you to provide me with the ResponseGenerator you'd like me to use."
TypesThere are three (3) types of Dependency Injection: Constructor Injection, Setter Injection, and Interface Injection. You've just seen an example of Constructor Injection. I'm not going to talk about or show Interface Injection for several reasons. (I've never used it and the other two are much more common.) Setter Injection I'm sure you can picture, but just in case, see the example below.
public class RequestHandler {
private ResponseGenerator responseGenerator;
public void setResponseGenerator(ResponseGenerator responseGenerator) {
this.responseGenerator = responseGenerator;
}
}
Constructor vs Setter InjectionThe primary distinction is that Constructor Injection provides a usable object (presumably) immediately after construction. This means no worries of running into exceptions because you instantiated an object but forgot to set one of its dependencies. So what about when you're dealing with quite a few dependencies? Either your constructor gets long, or you're forcing many setter method calls to create a usable object. Unless you have a good reason to use Setter Injection, I'd stick to Constructor Injection as a rule of thumb. (And stay away from using a combination if at all possible !!! My pet peeve.)
ProsOther than enabling loose coupling and increasing usability through inversion of control, the remaining major benefit is ease of testing. DI allows you to simply inject mock objects to unit test the class under test.
ConsWhen your class has lots of dependencies, it can get messy. Even though this could be an indication your class should be separated out into multiple classes (cohesion), it doesn't necessarily. So, from time to time, you will run into this.
More to ComeThere are more DI pros and cons, but nothing really worth talking about unless you're comparing against an alternative. Stay tuned and I'll be doing just that when I look at the idea of Service Locator as an alternative to Dependency Injection.
Other DI Links:WikipediaJames Lorenzen's Blog