Dagger2 簡單入門三部曲(一)——是什麼?

weixin_33860722發表於2018-11-27

Dagger2 簡單入門三部曲(一)——是什麼?
Dagger2 簡單入門三部曲(二)——為什麼使用?
Dagger2 簡單入門三部曲(三)——怎麼使用?(進行中)

Github 的介紹是:A fast dependency injector for Android and Java。(Android和Java的快速依賴注入器)

Dagger2 Github 地址

通過上邊瞭解到依賴注入這個詞,在AndroidJava中什麼是依賴注入呢?

依賴注入是什麼?

在軟體工程領域,依賴注入(Dependency Injection)是用於實現控制反轉(Inversion of Control)的最常見的方式之一。

上面提到控制反轉這個詞,那麼什麼是控制反轉呢?

控制反轉是什麼?

百度百科 是這麼介紹的:

控制反轉(Inversion of Control,縮寫為IoC),是物件導向程式設計中的一種設計原則,可以用來減低計算機程式碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI),還有一種方式叫“依賴查詢”(Dependency Lookup)。通過控制反轉,物件在被建立的時候,由一個調控系統內所有物件的外界實體,將其所依賴的物件的引用傳遞給它。也可以說,依賴被注入到物件中。

民間通俗理解:

就是你一個類裡面需要用到很多個成員變數,傳統的寫法,你要用這些成員變數,那麼你就 new 出來用唄~~
IoC的原則是:NO,我們不要new,這樣耦合度太高;你配置個 xml檔案,裡面標明哪個類,裡面用了哪些成員變數,等待載入這個類的時候,我幫你注入(new)進去;

這裡又有個問題,解耦解的誰和誰的耦?

下面來看實現一個導演名來搜尋電影的程式碼:

public class MovieLister {
    private MovieFinder finder;
    public MovieLister() {
        // MovieFinderImpl 實現裡具體的查詢所有電影方法
        finder = new MovieFinderImpl();
    }
    /**
    *  根據導演名來搜尋電影,返回電影集合
    *  @param arg 導演名
    */
    public Movie[] moviesDirectedBy(String arg) {
        // 獲取所有電影
        List allMovies = finder.findAll();
        for (Iterator it = allMovies.iterator(); it.hasNext();) {
            Movie movie = (Movie) it.next();
            // 移除不是該導演的電影
            if (!movie.getDirector().equals(arg)) it.remove();
        }
        return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
    }
    ...
}

/**
*  抽象實現介面
*/
public interface MovieFinder {
    List findAll();
}

以上程式碼看起來還是很美觀的,但是

當我們希望修改 finder,將finder替換為一種新的實現時(比如為MovieFinder增加一個參數列明Movie資料的來源是哪個資料庫),我們不僅需要修改MovieFinderImpl類,還需要修改我們MovieLister中建立MovieFinderImpl的程式碼

這就是依賴注入要處理的耦合。這種在MovieLister中建立MovieFinderImpl的方式,使得MovieLister不僅僅依賴於MovieFinder這個介面,它還依賴於MovieListImpl這個實現。 這種在一個類中直接建立另一個類的物件的程式碼, 是一種導致耦合的方式。

那麼我們如何去實現依賴注入從而達到解耦呢?

常用的有三種方式實現

  • 建構函式 注入(Contructor Injection)

繼續拿上面的程式碼來分析,通過建構函式注入可以讓MovieLister就只依賴於我們定義的MovieFinder介面,而不依賴於MovieFinder的實現了,這就減少了一個耦合。實現的程式碼如下:

public class MovieLister {
    private MovieFinder finder;
    public MovieLister(MovieFinder finder) {
        this.finder = finder;
    }
    ...
}
  • setter 注入

下面的實現也是減去了MovieFinderImpl的耦合

public class MovieLister {
    private MovieFinder finder;
    ...
    public void setFinder(MovieFinder finder) {
        this.finder = finder;
    }
}
  • 介面 注入

首先要建立一個注入使用的介面:

public interface InjectFinder {
    void injectFinder(MovieFinder finder);
}

之後,我們讓MovieLister實現這個介面

class MovieLister implements InjectFinder {
    private MovieFinder finder;
    ...
    public void injectFinder(MovieFinder finder) {
      this.finder = finder;
    }
    ...
}

這裡貼出利用介面注入實現解耦後的完整程式碼:

// MovieFinder
public interface MovieFinder {
    List findAll();
}
// MovieFinderImpl 具體實現
public class MovieFinderImpl implements MovieFinder {

    private static final String TAG = "MovieFinderImpl";

    @Override
    public List findAll() {
        Log.e(TAG, "findAll: 查詢所有電影");
        return new ArrayList();
    }
}

先定義一個介面
public interface InjectFinder {
    void injectFinder(MovieFinder finder);
}

實現該介面
public class MovieLister implements InjectFinder{

    private static final String TAG = "MovieLister";

    private MovieFinder finder;

    /**
     *  根據導演名來搜尋電影,返回電影集合
     *  @param arg 導演名
     */
    public Movie[] moviesDirectedBy(String arg) {
        // 獲取所有電影
        List allMovies = finder.findAll();
        // 簡單列印語句
        Log.e(TAG, "moviesDirectedBy: 移除不是"+arg+"導演的電影" );
        return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
    }

    @Override
    public void injectFinder(MovieFinder finder) {
        this.finder = finder;
    }
}

呼叫:
MovieFinder movieFinder = new MovieFinderImpl();
MovieLister movieLister = new MovieLister();
// 這裡通過介面注入
movieLister.injectFinder(movieFinder);
movieLister.moviesDirectedBy("張藝謀");

不出意外,執行之後會得到如下的顯示結果:


1942372-0fbd6c1f360c30f8.png
這是輸出的結果

參考-----依賴注入原理

綜上所述

Dagger2 是一個依賴注入框架,用於實現控制反轉的一種方式,主要是為了降低程式碼之間的耦合度。常見的依賴注入解耦方式有:建構函式注入、setter 注入、介面注入。

控制反轉的實現還有另一種方式是依賴查詢,這裡暫時不深入研究了。

文章到這裡就結束了,下篇文章介紹,為什麼使用 Dagger2。

相關文章