IoC: Inversion of Controlhtml
IoC是一種模式。目的是達到程序的複用。下面的兩篇論文是對IoC的權威解釋:java
一個對IoC形象化的描述,出自論文 http://www.digibarn.com/friends/curbow/star/XDEPaper.pdf 中的:編程
Don‘t call us, we’ll call you (Hollywood’s Law). A tool should arrange for Tajo to notify it when the user wishes to communicate some event to the tool, rather than adopt an 「ask the user for a command and execute it」 model.
當用戶(人、程序)要使用一個工具的時候,讓框架來激活這個工具,而不是讓用戶執行一些命令來激活它。segmentfault
即,原則是,使用組件的地方,只須要知道要使用什麼樣的組件,它會來自某個地方,但不須要知道組件具體是誰。api
按照這個原則開發的系統,實現了各組件之間相互依賴的解耦。即替換某個組件,不須要修改使用這個組件的組件。緩存
在編程語言實現上,IoC所涉及的工做主要有:oracle
IoC有不少具體的實現模式:框架
(1)Dependency Injection (DI) 依賴注入編程語言
組件管理器將組件注入到使用組件的對象中。函數
// Java示例:接口方法注入 // 注入依賴的接口 public interface InjectFinder { void injectFinder(MovieFinder finder); } // 注入依賴的接口 public interface InjectFinderFilename { void injectFilename(String filename); } // 注入器接口 public interface Injector { public void inject(Object target); } // == // 僅爲InjectFinder組件 class MovieLister implements InjectFinder { public void injectFinder(MovieFinder finder) { this.finder = finder; } } // 既是InjectFinderFilename組件,又是InjectFinder接口的注入器 class ColonMovieFinder implements Injector, InjectFinderFilename { public void injectFilename(String filename) { this.filename = filename; } public void inject(Object target) { ((InjectFinder) target).injectFinder(this); } } // 僅爲InjectFinderFilename接口的注入器 class FinderFilenameInjector implements Injector { public void inject(Object target) { ((InjectFinderFilename)target).injectFilename("movies1.txt"); } } // == class Tester { private Container container; private void configureContainer() { container = new Container(); // 註冊組件。完成建立組件。 registerComponents(); // 註冊注入器。完成組件注入。 registerInjectors(); container.start(); } private void registerComponents() { // 這裏模式是 組件名 - 組件 container.registerComponent("MovieLister", MovieLister.class); container.registerComponent("MovieFinder", ColonMovieFinder.class); } private void registerInjectors() { // 這裏的模式是 注入接口 - 注入器 // 容器會遍歷全部的組件,若是組件實現了注入接口,將調用對應的注入器,將這個組件做爲參數,傳遞給注入器 container.registerInjector(InjectFinder.class, container.lookup("MovieFinder")); container.registerInjector(InjectFinderFilename.class, new FinderFilenameInjector()); } public static void main(String[] args) { configureContainer(); MovieLister lister = (MovieLister)container.lookup("MovieLister"); Movie[] movies = lister.moviesDirectedBy("Sergio Leone"); assertEquals("Once Upon a Time in the West", movies[0].getTitle()); } }
(2)Service Locator 服務定位器
組件管理器將組件交給一個全局的服務者。組件的使用者主動向這個全局的服務者索取須要的組件。