IoC控制反轉與DI依賴注入

IoC控制反轉與DI依賴注入

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) 依賴注入編程語言

組件管理器將組件注入到使用組件的對象中。函數

  • 構造函數方式注入。被注入的對象在構造器中傳入。
  • 設值方法注入。經過setter方法注入。
  • 接口方法注入。須要被注入的類實現一個具體的接口,由一個注入器調用這個接口方法,完成組件注入。
// 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 服務定位器

組件管理器將組件交給一個全局的服務者。組件的使用者主動向這個全局的服務者索取須要的組件。

參考

本文連接:http://www.cnblogs.com/afarmer/p/4259133.html

相關文章
相關標籤/搜索