There seems to be almost universal agreement that the Dependency Injection software design pattern is a Good Thing. I agree. But I think its interesting to examine 2 cases where naive Dependency Injection doesnt work and a Service Locator approach is useful.
- Replaceable Parts: When the lifespan of the injected depedency is shorter than the containing object.
- Unknowable Dependencies: When an objects dependencies are unknowable at the time it is initialized.
A car is composed of parts, many of which will wear out or break before the car is disposed of: oil, brake discs, tyres, filters, etc. They must be replaceable. Some software objects are the same: database connections, sockets, references to external resources and the like can all become invalid and need replacing.
So if you inject a database connectioninto a long lifespan container object, and it breaks, the container will need to replace it, or break itself. There are two options:
- Use a Service Locator pattern instead for replacable objects, and look them up again if they break (ie failover).
- Rather than injecting the connection, inject the connection factory, which transparently does the failover. A kind of localized Service Locator. Effectively, ensures that the injected dependency’s lifespan is as long as the containg object.
If a container is going to dynamically instantiate classes, or otherwise behave autonomously, it may not not possible to know its dependencies at creation time.
As an example, consider container objects that can support arbritrary plugins, such as IDEs. They act as factories, creating other objects within themselves, after they are created, based on configuration data. To do so, they will need some kind of Service Locator.
Another less familar example from artificial intelligence is Autonomous Agents. Such objects may be deliberately designed to make new and unknowable decisions after creation time, that in term call for new dependencies to be satisfied.
The common link between these cases is Non-Determism. Dependency Injection works really well when components behavior is deterministic, but in general objects with non-determinsitc behavior cannot hope to define a fixed, finite set of dependent objects at creation time.
Rather than simplistic message “Dependency Injection is better than Service Locators”, we need to understand “When is Dependency Injection is better than a Service Locator?”.