通俗理解IOC/DI,控制反轉-依賴注入的思想

        最近在看一些文章的時候,無意間看到別人分享的關於依賴注入和控制反轉的最通俗的解釋,在此記一筆

首先要知道,IOC不是一種技術,只是一種編程思想,它能指導我們如何設計出鬆耦合、更優良的程序。我們平常開發一個應用程序,都是由我們在類內部主動創建依賴對象,從而導致類與類之間高耦合,對後期的擴展性和調試維護都是多少帶來不便,而提出了IOC容器思想後,我們在應用層開發時,所需要依賴的類的創建和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,所以對象與對象之間是 鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程序的整個體系結構變得非常靈活。

-----


網上有一個通俗的解釋是這樣的,非常便於記憶:


          1.1  首先想說說IOC(Inversion of Control,控制反轉),這是什麼意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪裏有長得漂亮身材又好的×××姐,然後打聽她們的興趣愛好、qq號、電話號、ip號、iq號………,想辦法認識她們,投其所好送其所要,然後嘿嘿……這個過程是複雜深奧的,我們必須自己設計和麪對每個環節。傳統的程序開發也是如此,在一個對象中,如果要使用另外的對象,就必須得到它(自己new一個,或者從JNDI中查詢一個),使用完之後還要將對象銷燬(比如Connection等),對象始終會和其他的接口或類藕合起來。


  那麼IOC是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個列表,告訴它我想找個什麼樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周杰倫,速度像卡洛斯,技術像齊達內之類的,然後婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛、結婚就行了。簡單明瞭,如果婚介給我們的人選不符合要求,我們就會拋出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。而對於IOC的概念,就是所有的類的創建、銷燬都由 IOC容器來控制,也就是說控制對象生存週期的不再是引用它的對象,而是IOC容器。對於某個具體的對象而言,以前是它控制其他對象,現在是所有對象都被IOC容器控制,所以這叫控制反轉。


         2.2、DI(依賴注入)

  IOC的一個重點是在系統運行中,動態的向某個對象提供它所需要的其他對象。這一點是通過DI(Dependency Injection,依賴注入)來實現的。比如對象A需要操作數據庫,以前我們總是要在A中自己編寫代碼來獲得一個Connection對象,有了 IOC容器我們就只需要告訴容器,A中需要一個Connection,至於這個Connection怎麼構造,何時構造,A不需要知道。在系統運行時,容器會在適當的時候製造一個Connection,然後像打針一樣,注射到A當中,這樣就完成了對各個對象之間關係的控制。A需要依賴 Connection才能正常運行,而這個Connection是由容器注入到A中的,依賴注入的名字就這麼來的。那麼DI是如何實現的呢? Java 、php等都引入了一個重要機制,即反射(reflection),它允許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性


  所以控制反轉IOC(Inversion of Control)是說創建對象的控制權進行轉移,以前創建對象的主動權和創建時機是由自己把控的,而現在這種權力轉移到第三方,比如轉移交給了IOC容器,它就是一個專門用來創建對象的工廠,你要什麼對象,它就給你什麼對象,有了 IOC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IOC容器了,通過IOC容器來建立它們之間的關係。


總結:控制的什麼被反轉了?就是:獲得依賴對象的方式反轉了。


下面列舉一個簡單的IOC/DI示例,進一步掌握這個概念到底是個什麼鬼!


代碼示意:

代碼示意:


<?php
/**
 * 沒有IoC/DI的時候,常規的A類使用C類的示例
 */
/**
 * Class C
 */
class C
{
    public function say()
    {
        echo 'hello';
    }
}
/**
 * Class A
 */
class A
{
    private $c;
    public function __construct()
    {
        $this->c = new C(); // 實例化創建C類
    }
    public function sayC()
    {
        echo $this->c->say(); // 調用C類中的方法
    }
}
$a = new a();
$a->sayC();

當有了IoC/DI的容器後,A類不再主動去創建C了,如下圖所示:

0.png

而是被動等待,等待IoC/DI的容器獲取一個C的實例,然後反向的注入到A類中,如下圖所示:

1.png

代碼示意:

<?php/**
 * 當有了IoC/DI的容器後,a類依賴c實例注入的示例
 *//**
 * Class c
 */class c{    public function say()
    {        echo 'hello';
    }
}/**
 * Class a
 */class a{    private $c;    public function setC(C $c)
    {        $this->c = $c; // 實例化創建C類
    }    public function sayC()
    {        echo $this->c->say(); // 調用C類中的方法
    }
}

$c = new C();
$a = new a();
$a->setC($c);
$a->sayC();


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章