新的一个注册注入器的步骤是注册依赖的组件。每一个注入接口需要一些用来注入依赖对象的代码。这里我通过使用容器的注册注入器对象来实现。每一个注入器对象实现了注入器接口。
class Tester...
private void registerInjectors() {
container.registerInjector(InjectFinder.class, container.lookup("MovieFinder"));
container.registerInjector(InjectFinderFilename.class, new FinderFilenameInjector());
}
public interface Injector {
public void inject(Object target);
}
当依赖是一个为这个容易编写的类时,为这个组件实现注入器接口本身是有意义的,就像我在movie finder中所做的那样。对于一般的类,例如字符串,我在一段配置代码中使用了内部类。
class ColonMovieFinder implements Injector......
public void inject(Object target) {
((InjectFinder) target).injectFinder(this);
}
class Tester...
public static class FinderFilenameInjector implements Injector {
public void inject(Object target) {
((InjectFinderFilename)target).injectFilename("movies1.txt");
}
}
让后再测试中使用这个容器。
class IfaceTester...
public void testIface() {
configureContainer();
MovieLister lister = (MovieLister)container.lookup("MovieLister");
Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
assertEquals("Once Upon a Time in the West", movies[0].getTitle());
}
容器使用了声明的注入器接口来计算出依赖,并且注入器注入了正确的依赖。(具体的容器实现在这里并不是什么重要的技术,这里我不做展示。)
使用Service Locator
依赖注入的最大好处在于:它消除了MovieLister类对具体MovieFinder实现类的依赖。这样一来,我就可以把MovieLister类交给朋友,让他们根据自己的环境插入一个合适的MovieFinder实现即可。不过,Dependency Injection模式并不是打破这层依赖关系的唯一手段,另一种方法是使用Service Locator模式。
Service Locator模式背后的基本思想是:有一个对象(即服务定位器)知道如何获得一个应用程序所需的所有服务。也就是说,在我们的例子中,服务定位器应该有一个方法,用于获得一个MovieFinder实例。当然,这不过是把麻烦换了一个样子,我们仍然必须在MovieLister中获得服务定位器,最终得到的依赖关系如图3 所示:
图3:使用Service Locator 模式之后的依赖关系