Dagger2 簡單入門三部曲(一)——是什麼?
ofollow,noindex">Dagger2 簡單入門三部曲(一)——是什麼?
Dagger2 簡單入門三部曲(二)——為什麼使用?(進行中)
Dagger2 簡單入門三部曲(三)——怎麼使用?(進行中)
Github 的介紹是:A fast dependency injector for Android and Java。(Android和Java的快速依賴注入器)
通過上邊瞭解到 依賴注入這個詞
,在 Android
和 Java
中什麼是 依賴注入
呢?
依賴注入是什麼?
在軟體工程領域,依賴注入(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("張藝謀");
不出意外,執行之後會得到如下的顯示結果:

這是輸出的結果
綜上所述
Dagger2
是一個依賴注入框架,用於實現控制反轉的一種方式,主要是為了降低程式碼之間的耦合度。 常見的依賴注入解耦方式有:建構函式注入、setter 注入、介面注入。
控制反轉的實現還有另一種方式是 依賴查詢
,這裡暫時不深入研究了。
文章到這裡就結束了,下篇文章介紹,為什麼使用 Dagger2。