新的一個(gè)注冊(cè)注入器的步驟是注冊(cè)依賴的組件。每一個(gè)注入接口需要一些用來注入依賴對(duì)象的代碼。這里我通過使用容器的注冊(cè)注入器對(duì)象來實(shí)現(xiàn)。每一個(gè)注入器對(duì)象實(shí)現(xiàn)了注入器接口。
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);
}
當(dāng)依賴是一個(gè)為這個(gè)容易編寫的類時(shí),為這個(gè)組件實(shí)現(xiàn)注入器接口本身是有意義的,就像我在movie finder中所做的那樣。對(duì)于一般的類,例如字符串,我在一段配置代碼中使用了內(nèi)部類。
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");
}
}
讓后再測(cè)試中使用這個(gè)容器。
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());
}
容器使用了聲明的注入器接口來計(jì)算出依賴,并且注入器注入了正確的依賴。(具體的容器實(shí)現(xiàn)在這里并不是什么重要的技術(shù),這里我不做展示。)
使用Service Locator
依賴注入的最大好處在于:它消除了MovieLister類對(duì)具體MovieFinder實(shí)現(xiàn)類的依賴。這樣一來,我就可以把MovieLister類交給朋友,讓他們根據(jù)自己的環(huán)境插入一個(gè)合適的MovieFinder實(shí)現(xiàn)即可。不過,Dependency Injection模式并不是打破這層依賴關(guān)系的唯一手段,另一種方法是使用Service Locator模式。
Service Locator模式背后的基本思想是:有一個(gè)對(duì)象(即服務(wù)定位器)知道如何獲得一個(gè)應(yīng)用程序所需的所有服務(wù)。也就是說,在我們的例子中,服務(wù)定位器應(yīng)該有一個(gè)方法,用于獲得一個(gè)MovieFinder實(shí)例。當(dāng)然,這不過是把麻煩換了一個(gè)樣子,我們?nèi)匀槐仨氃贛ovieLister中獲得服務(wù)定位器,最終得到的依賴關(guān)系如圖3 所示:
圖3:使用Service Locator 模式之后的依賴關(guān)系