Angular4學習筆記(四)- 依賴注入

概念

依賴注入是一種設計思想,並非某一類語言所特有的,所以能夠參考開濤大神關於學習Java語言的Spring框架時對其的解釋:html

DI—Dependency Injection,即「依賴注入」:是組件之間依賴關係由容器在運行期決定,形象的說,即由容器動態的將某個依賴關係注入到組件之中。依賴注入的目的並不是爲軟件系統帶來更多功能,而是爲了提高組件重用的頻率,併爲系統搭建一個靈活、可擴展的平臺。經過依賴注入機制,咱們只須要經過簡單的配置,而無需任何代碼就可指定目標須要的資源,完成自身的業務邏輯,而不須要關心具體的資源來自何處,由誰實現。
理解DI的關鍵是:「誰依賴誰,爲何須要依賴,誰注入誰,注入了什麼」,那咱們來深刻分析一下:segmentfault

  • 誰依賴於誰:固然是應用程序依賴於IoC容器;
  • 爲何須要依賴:應用程序須要IoC容器來提供對象須要的外部資源;
  • 誰注入誰:很明顯是IoC容器注入應用程序某個對象,應用程序依賴的對象;
  • 注入了什麼:就是注入某個對象所須要的外部資源(包括對象、資源、常量數據)。

IoC和DI由什麼關係呢?其實它們是同一個概念的不一樣角度描述,因爲控制反轉概念比較含糊(可能只是理解爲容器控制對象這一個層面,很難讓人想到誰來維護對象關係),因此2004年大師級人物Martin Fowler又給出了一個新的名字:「依賴注入」,相對IoC 而言,「依賴注入」明確描述了「被注入對象依賴IoC容器配置依賴對象」1數組

Angular中的依賴注入

Angular中能夠在app.module.ts中進行全局聲明,也能夠在組件內部根據特定需求實現特定聲明。
聲明是經過屬性providers實現的,顧名思義,它是一個對象提供者,複數形式表名其爲數組形式。且子類型爲Provide,它位於@angular/core中,實現以下:app

export interface TypeProvider extends Type<any> {
}
export interface ValueProvider {
  provide: any;
  useValue: any;
  multi?: boolean;
}
export interface ClassProvider {
  provide: any;
  useClass: Type<any>;
  multi?: boolean;
}
export interface ExistingProvider {
  provide: any;
  useExisting: any;
  multi?: boolean;
}
export interface FactoryProvider {
  provide: any;
  useFactory: Function;
  deps?: any[];
  multi?: boolean;
}

export declare type Provider =
  TypeProvider | ValueProvider | ClassProvider | ExistingProvider | FactoryProvider | any[];

能夠看到,Provider共有5個明確的子類,也決定了其使用方式的數量。因爲全局聲明和組件內部聲明的方式差異不大,可見的區別是在app.module.ts中屬性providers是在模塊註解@NgModule中聲明而組件中是經過註解@Component聲明。所以實現方式不對全局和組件加以區分。框架

因爲是初學,此處僅列舉經常使用的幾種方式:useClassuseFactoryuseValuedom

useClass

providers: [{provide: DefaultBookService, useClass: DefaultBookService}]
其中provide定義了token,而useClass則指明瞭使用的類,此處因爲token和實現類相同,均爲DefaultBookService所以能夠簡寫爲providers: [DefaultBookService]ide

useFactory

providers: [{
    provide: DefaultBookService, useFactory: () => {
      const rdm = Math.random() < 0.5;
      if (rdm) {
        return new DefaultBookService();
      } else {
        return new HuaZhangBookService();
      }
    }

HuaZhangBookServiceDefaulteBookService的一個子類。根據狀況返回所需注入的對象。函數

若是經過依賴注入的對象同時依賴另外一個經過依賴注入的對象應如何實現呢?好比DefaultBookService,它的構造函數爲:
constructor(public logger: LoggerService) { },而LoggerService也是經過依賴注入-即不須要本身手工new LoggerService()-時應該怎麼辦?在類FactoryProvider中提供了一個名叫deps的參數,它能夠幫助咱們實現依賴對象的引用。用法以下:學習

providers: [{
    provide: DefaultBookService, useFactory: (logger: LoggerService) => {
      const rdm = Math.random() < 0.5;
      if (rdm) {
        return new DefaultBookService(logger);
      } else {
        return new HuaZhangBookService(logger);
      }
    }, deps: [LoggerService]
  }, LoggerService]

deps是一個任意類型的數組,爲何呢,由於類的參數不會只有一個,當構造方法中有多個參數時,可同時依賴多個不一樣類型的對象。this

useValue

基本用法:
{provide: 'IS_DEV_ENV', useValue: Math.random() < 0.5}
擴展用法:

providers: [{
    provide: DefaultBookService, useFactory: (logger: LoggerService, isDev) => {
      if (isDev) {
        return new DefaultBookService(logger);
      } else {
        return new HuaZhangBookService(logger);
      }
    }, deps: [LoggerService, 'IS_DEV_ENV']
  },
    LoggerService, {provide: 'IS_DEV_ENV', useValue: Math.random() < 0.5}
  ]

能夠看到,在useFactory的箭頭表達式中有兩個參數,他們依次對應deps中的token,即isDev對應token爲IS_DEV_ENV的對象,而它正是使用了本小節中所涉及的useValue形式,它返回一個boolean對象。

另外須要注意的是,token不止能指定特定的類,也能夠指定特定的值。

multi

參考

其餘

  • 以上咱們簡單介紹了幾種Angular實現依賴注入的方式,可是還須要提供使用它的條件,在Angular中,只有當組件或者服務被註解@Injectable或其子類如@Component修飾後,纔可以使用,建議不管是否使用依賴注入,都使用@Injectable修飾。
  • 能夠經過構造方法的參數來放置經過依賴生成的對象:constructor(private bookService: DefaultBookService) { },此時,其餘方法中直接使用this.bookService來調用DefaultBookService中的方法了。
  • 經過依賴注入傳入的對象,能夠經過Injector來進行訪問,它位於@angular/core包中,所以上面的構造方法能夠這樣聲明constructor(private injector: Injector) { },經過this.injector.get(DefaultBookService)來獲取DefaultBookService對象並調用其中的方法,但不建議這樣作,由於不如直接傳入所需對象來的明確。
  • app.module.ts中使用useFactory而且使用箭頭表達式來實現時,註冊的組件會報錯,至今無解,相關問題已發至segmentFault,哪位大神若是知道,煩請告訴,跪謝。
  • 關於Token的學習能夠參考Angular 4 依賴注入教程之八 InjectToken的使用

  1. 若是想要更加深刻的瞭解IoC和DI,請參考大師級人物Martin Fowler的一篇經典文章《Inversion of Control Containers and the Dependency Injection pattern》,原文地址:http://www.martinfowler.com/articles/injection.html。

相關文章
相關標籤/搜索