控制反轉(IOC)/依賴注入(DI)理解

我的學習筆記,來自Acodehtml

一、術語java

控制反轉/反向控制,英文全稱「Inversion of Control」,簡稱IoC。程序員

依賴注入,英文全稱「Dependency Injection」,簡稱DI。數據庫

 

聽說是Martin Fowler對控制反轉的原理進行了深刻的探索後,爲控制反轉起了個新的名字叫「依賴注入」。也就是說,這兩個術語講的是同一個事物。函數

 

二、控制反轉的「奧義」學習

  「實現必須依賴抽象,而不是抽象依賴實現」。this

 

三、實例理解spa

  只看了控制反轉的奧義,對於通常人來講仍是難以理解,就比如一位功夫大師告訴咱們「無招勝有招」,資質平平的我仍是沒法理解到大師們的話,因而就凌亂了...code

  下面,仍是經過實際的程序來理解一下控制反轉。htm

假設場景:從SQL Server數據庫中獲取數據。

【普通方法】

通常人會這麼寫程序:

首先,實現一個對數據庫進行各類操做的類SqlServerDataBase:

 1 /*
 2 *SqlServerDataBase.java
 3 **/
 4 
 5 public class SqlServerDataBase {
 6     
 7     /*
 8     *構造函數、數據庫鏈接等操做對應的語句
 9     */
10 
11     //從SQL Server數據庫中獲取數據
12     public List getDataFromSqlServer() {
13         //獲取數據的具體語句
14     }
15 }

而後,就能夠在業務層經過對象的實例來獲取須要的數據:

 1 /*
 2 *Business.java
 3 **/
 4 
 5 public class Business{
 6     private SqlServerDataBase db = new SqlServerDataBase();
 7 
 8     //從SQL Server數據庫中獲取數據
 9     public void getData() {
10         List list = db.getDataFromSqlServer();
11     }
12 
13 }

這麼一看,感受代碼寫得很不錯啊,完美地知足了需求。但是,某一天,決定要將數據庫更換爲MySQL,因而咱們歷盡千辛萬苦寫的兩個程序都不能用了,咱們須要重寫下面的代碼:

/*
*MySQLDataBase.java
**/

public class MySQLDataBase {
    
    /*
    *構造函數、數據庫鏈接等操做對應的語句
    */

    //從MySQL數據庫中獲取數據
    public List getDataFromMySQL() {
        //獲取數據的具體語句
    }
}

/*
*Business.java
**/

public class Business{
    private MySQLDataBase db = new MySQLDataBase();

    //從MySQL數據庫中獲取數據
    public void getData() {
        List list = db.getDataFromMySQL();
    }

}

咱們又費勁巴拉地寫了上面的兩個文件。這時,客戶又決定要用Oracle做爲數據!!!這時,估計你的心裏是無比的崩潰的。爲了毛爺爺,咱們忍了,再次寫了新的程序。

當寫了以Oracle爲數據庫的程序後,客戶說要用MongoDB做爲數據庫!!!這時,感受不再要當程序員了。

 

總結:

  從上面的例子中能夠看出,一旦客戶的業務需求變了,咱們寫的代碼基本就白搭了,還要重寫新的代碼。這是爲何呢?緣由是:Business類的中使用到了具體的數據庫對應的類,一旦要使用的數據庫改變了,Business中的代碼也得跟着改啊(getDataFromSqlServer()->getDataFromMySQL()->...)。

 

教訓:

  要實現一種代碼能夠屢次重複利用,不依賴於具體業務的代碼,實現Business類的重用。這時,咱們想到了大神告訴咱們的控制反轉的奧義「實現必須依賴抽象,而不是抽象依賴實現」。

 

【IoC方式實現】

一、首先,定義一個從數據庫中獲取數據的接口DataBase,做爲一個接口,它裏面只有方法的聲明,此處咱們須要一個從數據庫中獲取數據的方法:getData()。

 1 /*
 2 *DataBase.java
 3 */
 4 
 5 public interface DataBase{
 6     //該方法用來獲取數據
 7     public void getData();
 8 }

二、接着,此時客戶要求採用SQL Server做爲項目的數據庫,那麼就實現一個負責從SQL Server數據庫中獲取數據的類SqlServerDataBase:

 1 /*
 2 *SqlServerDataBase.java
 3 */
 4 
 5 public class SqlServerDataBase implements DataBase{
 6     //該方法用來獲取數據
 7     public void getData() {
 8         //如下是具體從SQL Server數據庫中取數據的代碼
 9         ......
10     }
11 }

該類具體實現了從SQL Server數據庫中獲取數據的過程。

三、此時,業務須要從數據庫中獲取數據,實現業務類Business(注意該類的寫法,很重要):

 1 /*
 2 *Business.java
 3 */
 4 
 5 public class Business {
 6     //針對接口DataBase定義變量
 7     private DataBase db;
 8 
 9     public void setDataBase(DataBase db) {
10         this.db=db;
11     }
12 
13     //根據注入的數據庫類,從xxx數據庫中獲取數據
14     public void getData() {
15         db.getData();
16     }
17 }

注意的地方:

  (1)在第7行,定義了一個操做數據庫的接口的變量db,並非依賴於具體實現的類的變量;

  (2)定義了setDataBase()方法,該方法實現了具體實現的數據庫操做類的變量的注入;

  (3)getData()方法或根據實際注入的數據庫類型獲取數據。

總結:

  能夠看出,該方法的實現是依賴於抽象,而非依賴於具體的實現,是否是想到了IoC的終極奧義「實現必須依賴抽象,而不是抽象依賴實現」。

四、經過3中的Business類,實現了代碼的重用(我的感受,也就是對業務層也實現了「兼容性強的一種封裝」,所以才實現了代碼的重用),下面就看一下怎麼根據具體的數據庫類型來實現數據庫的取數據:

 1 /*
 2 *TestBusiness.java
 3 */
 4 
 5 public class TestBusiness {
 6     private Business Business = new Business();
 7 
 8     //根據注入的數據庫類,從SQL Server數據庫中獲取數據
 9     public void getData() {
10         business.setDataBase(new SqlServerDataBase());
11         business.getData();
12     }
13 }

在第10行中,咱們將SQL Server類的變量的注入到業務類Business中,也就實現了從SQL Server數據庫中取數據的操做。此時,咱們就不再怕客戶更換數據庫了。

假設客戶要採用MySQL做爲數據庫,那麼,咱們須要作的只有兩點:

(1)實現基於MySQL的取數據的類MySQLDataBase

 1 /*
 2 *MySQLDataBase.java
 3 */
 4 
 5 public class MySQLDataBase implements DataBase{
 6     //該方法用來獲取數據
 7     public void getData() {
 8         //如下是具體從MySQL數據庫中取數據的代碼
 9         ......
10     }
11 }

(2)更改注入的數據庫類型

 1 /*
 2 *TestBusiness.java
 3 */
 4 
 5 public class TestBusiness {
 6     private Business Business = new Business();
 7 
 8     //根據注入的數據庫類,從MySQL數據庫中獲取數據
 9     public void getData() {
10         business.setDataBase(new MySQLDataBase());
11         business.getData();
12     }
13 }

咱們只須要更改第10行中藥注入的數據庫類型,就完成了全部的工做。

 

此時,再次理解下IoC的終極奧義:實現必須依賴抽象,而不是抽象依賴實現。(修煉的境界又提高了一層)

 

轉載請註明出處:http://www.cnblogs.com/acode/p/5356686.html

相關文章
相關標籤/搜索