android開源庫---Dagger2學習準備(依賴注入)
我這次準備介紹的是Dagger2的使用。
那麼學習這個之前我要做下準備就是了解為什麼要使用這個,那麼我們就必須要先了解一下什麼是依賴注入。
什麼是依賴注入
依賴注入控制反轉的一種實現方式。
控制反轉即IoC (Inversion of Control),它把傳統上由程式程式碼直接操控的物件的呼叫權交給容器,通過容器來實現物件元件的裝配和管理。所謂的“控制反轉”概念就是對元件物件控制權的轉移,從程式程式碼本身轉移到了外部容器。
IoC是一個很大的概念,可以用不同的方式來實現。其主要實現方式有兩種:<1>依賴查詢(Dependency Lookup):容器提供回撥介面和上下文環境給元件。EJB和Apache Avalon都使用這種方式。<2>依賴注入(Dependency Injection):元件不做定位查詢,只提供普通的Java方法讓容器去決定依賴關係。後者是時下最流行的IoC型別,其又有介面注入(Interface Injection),設值注入(Setter Injection)和構造子注入(Constructor Injection)三種方式。
(我的畫圖功力有限這次我用的xmind( ⊙ o ⊙ )!)
當下比較流行控制反轉的實現方式是依賴注入,因為它是一種更可取的方式:讓容器全權負責依賴查詢,受管元件只需要暴露JavaBean的setter方法或者帶引數的構造子或者介面,使容器可以在初始化時組裝物件的依賴關係。
其與依賴查詢方式相比,主要優勢為:
- 查詢定位操作與應用程式碼完全無關
- 不依賴於容器的API,可以很容易地在任何容器以外使用應用物件
- 不需要特殊的介面,絕大多數物件可以做到完全不必依賴容器
(依賴查詢我就看了一下不怎麼了解就不細說了-。-)
依賴注入的基本原則
依賴注入的基本原則是:應用元件不應該負責查詢資源或者其他依賴的協作物件。配置物件的工作應該由IoC容器負責,“查詢資源”的邏輯應該從應用元件的程式碼中抽取出來,交給IoC容器負責。
我個人理解就是,在程式中,一個物件中的方法需要依賴另一個物件,該物件中儲存其所依賴物件的例項,生成依賴物件的方式不再該物件中通過new建立,而是呼叫者外部建立依賴物件,然後通過一定的方式進行傳入。
舉個例子
一個女孩依賴一個男孩
public class Girl{
// 依賴類
private Boy boy;
public Girl(){
// 在當前物件中直接 new 出依賴類
boy = new Boy();
}
public void run(){
boy.run();
}
}
public class Boy {
String name;
public Boy(){
}
public void run(){
}
}
此時看著無大礙,那麼如果boy發生了變化,其構造方法發生了變化,需要傳入一個姓名。比如女孩依賴叫小明的那個男孩。那還那麼需要修改程式碼:
public class Boy {
String name;
public Boy(String name ){
// 修改了構造方法
this.name = name;
}
public void run(){
}
}
public class Girl{
// 依賴類
private Boy boy;
public Girl(){
// 因為Boy的構造方法發生變化,所以需要修改該處程式碼
boy = new Boy("小明");
}
public void run(){
boy.run();
}
}
修改了Boy的構造方法之後,因為Classes依賴Boy,所以其內部也需要修改。
如果又發生了變化,比如女孩依賴的是一個叫小明的有錢的男孩(你懂的-。-)那麼又要改變Boy的構造方法。這樣的話,一個還是不明顯,當工程量很浩大時,呵呵了。(自掛東南枝)
此時,我們可以將Boy該物件的例項化交給其呼叫者,通過某種方式傳入進來。這種模式就是依賴注入。
依賴注入的三種實現方式
- 構造子注入(Constructor Injection)
- 設值注入(Setter Injection)
- 介面注入(Interface Injection)
上面給出過圖了這裡我就 。。。。算了還是給張圖吧
1、構造方法注入(Constructor Injection)
該方式是通過構造方法將其所依賴的外部類物件傳入進來,是我認為的最簡單的方式。其實現方式如下,我們修改之前的程式碼:
public class Girl{
// 依賴類
private Boy boy;
/**
* 構造方法注入,通過構造方法傳入該物件
* @param boy
*/
public Girl(Boy boy) {
this.boy = boy;
}
public void run() {
boy.run();
}
}
2、設值注入(Setter Injection)
通過手動方式呼叫set方法將Boy設定進來。
public class Girl{
//....
private Boy boy;
public void setBoy(Boy boy){
this.boy = boy;
}
//....
}
3、介面注入(Interface Injection)
介面方式是定義一個介面,該介面中宣告一個注入的方法,而需要注入的類實現該介面,實現介面中定義的方法。
首先,定義介面,宣告注入方法
public interface BoyInjection {
void inject(Boy boy);
}
實現介面中的方法
public class Girlimplements BoyInjection {
//....
private Boy boy;
@Override
public void inject(Boy boy) {
this.boy = boy;
}
//....
}
總結
如上的方式只不過是比較簡單的方式,真正的使用中,往往使用一些框架實現依賴注入。
Dagger2便是一個很好的依賴注入框架,我們接下來就要學習這個框架(我們做好準備接下來要開車了哈-。-)。
這裡我們認識了控制反轉和依賴注入,其實二者是一個概念。在傳統的設計過程中,通常由呼叫者來建立被呼叫的例項,控制反轉指的是建立被呼叫者的工作不再由呼叫者來完成,因此稱為控制反轉;建立被呼叫者 例項的工作通常由普通方式或者框架(Dagger2 等)來完成,然後注入呼叫者,因此也稱為依賴注入。