Merging the functionality provided by dependency injection with that given by a service locator is a straightforward, easy-to-understand process. Since I want to demonstrate how to use this approach with the earlier registry library, the first thing I must change is the definition of the registry locator, which needs to be injectable.
To make this change, the locator's originating class must no longer be a static factory, but a dynamic one instead. The following code sample clearly reflects this modification:
Done. Now that the "RegistryLocator" class can be instantiated, the next step is to make the client registry ask for the locator in its constructor. Again, the following snippet accomplishes this goal:
That looks much better, doesn't it? As you can see, now the client registry class accepts, through its constructor, an instance of the locator, which is stored as a protected property. This simple change demonstrates that injecting a service locator is in fact much simpler than one might think. Plus, there's an additional benefit to using this approach: now it's perfectly possible to replace the locator with a mock-up, which makes testing the client registry a breeze.
Unfortunately, an injected locator also has its own drawbacks. If the client registry needs to use a different registry backend, the only way to achieve this is to add a new factory method to the locator and call it explicitly. This isn't very flexible.
However, in those cases where collaborators of a client have a shorter life cycle than the client itself, injecting locators that are concrete factories, responsible for spawning only a single dependency, makes a lot of sense.
Well, having clarified those concepts, we still need to test the improved version of the registry library, once the previous changes have been properly implemented.
This will be done below, so keep reading.
A final example
As I promised above, here's a concrete example that shows how to work with the enhanced registry library, now that it uses an injected service locator:
// example injecting a service locator
// include the autoloader
// create an instance of the registry and save some data in it
// get the data from the registry
Although the above script does nothing spectacular, other than saving and retrieving some information about our fictional user, Mary Wilson, it does demonstrate how the functionality of dependency injection and service locators working together can help to write classes that are easier to test in isolation.
Naturally, if you've developed applications composed of a large number of object graphs, much more complex than the one above, dependency injection on its own is, in my opinion, the best approach. However, in relatively simple use cases, an injected locator may fit your needs.
In this second tutorial of the series, I attempted to show how the combined functionality provided by dependency injection and a service locator can be quite helpful in the construction of testable object graphs.
While the example that you just learned was pretty illustrative, it would be desirable to set up one that resembles a more realistic use case. Thus, in the next part I'm going to show you how to implement a service locator in the construction of a simple blog application.
Don't miss the next part!
blog comments powered by Disqus