關于依賴注入(DI) 和 控制反轉(IoC)的一點總結

一察迟、名詞解釋

IoC - Inversion of Control 控制反轉
DI - Dependency Injection 依賴注入
依賴倒置原則(DIP):一種軟件架構設計的原則(抽象概念),依賴倒置原則,它轉換了依賴盅抚,抽象模塊不依賴于具體模塊的實現(xiàn),而具體模塊依賴于抽象模塊定義的接口。通俗的講,就是抽象模塊定義接口莺琳,具體模塊負責實現(xiàn)。载慈。
控制反轉(IoC):一種反轉流惭等、依賴和接口的方式(DIP的具體實現(xiàn)方式)。
依賴注入(DI):IoC的一種實現(xiàn)方式办铡,用來反轉依賴(IoC的具體實現(xiàn)方式)辞做。
IoC容器 :依賴注入的框架,用來映射依賴寡具,管理對象創(chuàng)建和生存周期(DI框架)秤茅。

依賴注入(DI)是一個過程,通過這個過程童叠,對象可以通過構造函數(shù)參數(shù)嫂伞,工廠方法的參數(shù)或者在構造或返回對象實例后設置的屬性來定義它們的依賴關系從工廠方法。

依賴注入和控制反轉說的實際上是同一個東西拯钻,它們是一種設計模式,這種設計模式用來減少程序間的耦合撰豺。依賴注入和控制反轉是對同一件事情的不同描述粪般,從某個方面講,就是它們描述的角度不同污桦。

1亩歹、依賴注入是從應用程序的角度在描述,可以把依賴注入凡橱,即:應用程序依賴容器創(chuàng)建并注入它所需要的外部資源小作;

2、而控制反轉是從容器的角度在描述稼钩,即:容器控制應用程序顾稀,由容器反向的向應用程序注入應用程序所需要的外部資源。

整個過程中參與者都有誰坝撑?

一般有三方參與者静秆,一個是某個對象粮揉;一個是IoC/DI的容器;另一個是某個對象的外部資源抚笔。
1扶认、某個對象指的就是任意的、普通的PHP對象; 
2殊橙、IoC/DI的容器簡單點說就是指用來實現(xiàn)IoC/DI功能的一個框架程序辐宾;
3、對象的外部資源指的就是對象需要的膨蛮,但是是從對象外部獲取的叠纹,都統(tǒng)稱資源,比如:對象需要的其它對象鸽疾、或者是對象需要的文件資源等等吊洼。

二、控制反轉IoC進一步解釋

1制肮、如何反轉冒窍,反轉了什么

控制反轉顧名思義,就是要去反轉控制權豺鼻,那么到底是哪些控制被反轉了综液?控制反轉是指把對象的依賴管理從內部轉移至外部。

在單一職責原則的設計下儒飒,很少有單獨一個對象就能完成的任務谬莹。大多數(shù)任務都需要復數(shù)的對象來協(xié)作完成,這樣對象與對象之間就有了依賴桩了。一開始對象之間的依賴關系是自己解決的附帽,需要什么對象了就New一個出來用,控制權是在對象本身井誉。但是這樣耦合度就非常高蕉扮,可能某個對象的一點小修改就會引起連鎖反應,需要把依賴的對象一路修改過去颗圣。

如果依賴對象的獲得被反轉喳钟,具體生成什么依賴對象和什么時候生成都由對象之外的IOC容器來決定。對象只要在用到依賴對象的時候能獲取到就可以了在岂,常用的方式有依賴注入和依賴查找(Dependency Lookup)奔则。這樣對象與對象之間的耦合就被移除到了對象之外,后續(xù)即使有依賴修改也不需要去修改原代碼了蔽午。

2易茬、依賴注入

控制反轉是把對象之間的依賴關系提到外部去管理,可依賴是提到對象外面了及老,對象本身還是要用到依賴對象的疾呻,這時候就要用到依賴注入了除嘹。顧名思義,應用需要把對象所需要的依賴從外部注入進來岸蜗。IoC有2種常見的實現(xiàn)方式:依賴注入和服務定位尉咕。

控制反轉(IoC)一種重要的方式,就是將依賴對象的創(chuàng)建和綁定轉移到被依賴對象類的外部來實現(xiàn)璃岳。

依賴注入(DI)年缎,它提供一種機制,將需要依賴(具體模塊)對象的引用傳遞給被依賴(抽象模塊)對象铃慷。
實現(xiàn)方式:

方法一 構造函數(shù)注入
構造函數(shù)函數(shù)注入傳遞依賴单芜。根據DIP原則,我們知道抽象模塊不應該依賴于具體模塊犁柜,兩者應該依賴于抽象洲鸠。那么構造函數(shù)的參數(shù)應該是一個抽象類型。

方法二 屬性注入
屬性注入是通過屬性來傳遞依賴馋缅。

方法三 接口注入
相比構造函數(shù)注入和屬性注入扒腕,接口注入顯得有些復雜,使用也不常見萤悴。具體思路是先定義一個接口瘾腰,包含一個設置依賴的方法。然后依賴類覆履,繼承并實現(xiàn)這個接口蹋盆。

對于大型項目來說,相互依賴的組件比較多硝全。如果還用手動的方式栖雾,自己來創(chuàng)建和注入依賴的話,顯然效率很低伟众,而且往往還會出現(xiàn)不可控的場面岩灭。正因如此,IoC容器誕生了赂鲤。IoC容器實際上是一個DI框架,它能簡化我們的工作量柱恤。

它包含以下幾個功能:
1数初、動態(tài)創(chuàng)建、注入依賴對象梗顺。
2泡孩、管理對象生命周期。
3寺谤、映射依賴關系仑鸥。

三吮播、PHP代碼示例

PHP具體代碼實現(xiàn)的思路:


1、Ioc容器維護binding數(shù)組記錄bind方法傳入的鍵值對如:log=>FileLog, user=>User
2眼俊、在ioc->make('user')的時候意狠,通過反射拿到User的構造函數(shù),拿到構造函數(shù)的參數(shù)疮胖,發(fā)現(xiàn)參數(shù)是User的構造函數(shù)參數(shù)log,然后根據log得到FileLog环戈。
3、這時候我們只需要通過反射機制創(chuàng)建 $filelog = new FileLog();
4澎灸、通過newInstanceArgs然后再去創(chuàng)建new User($filelog);


interface log{
    public function write();
}

// 文件記錄日志
class FileLog implements Log{
    public function write(){
        echo 'file log write...';
    }
}

// 數(shù)據庫記錄日志
class DatabaseLog implements Log{
    public function write(){
        echo 'database log write...';
    }
}

class User{
    protected $log;
    public function __construct(Log $log){
        $this->log = $log;
    }
    public function login(){
        // 登錄成功院塞,記錄登錄日志
        echo 'login success...';
        $this->log->write();
    }
}

class Ioc{
    public $binding = [];

    public function bind($abstract, $concrete){
        //這里為什么要返回一個closure呢?因為bind的時候還不需要創(chuàng)建User對象性昭,所以采用closure等make的時候再創(chuàng)建FileLog;
        $this->binding[$abstract]['concrete'] = function ($ioc) use ($concrete) {
            return $ioc->build($concrete);
        };
    }

    public function make($abstract){
        // 根據key獲取binding的值
        $concrete = $this->binding[$abstract]['concrete'];

        return $concrete($this);
    }

    // 創(chuàng)建對象
    public function build($concrete) {
        $reflector = new ReflectionClass($concrete);
        $constructor = $reflector->getConstructor();
        if(is_null($constructor)) {
            return $reflector->newInstance();
        }
            $dependencies = $constructor->getParameters();
            $instances = $this->getDependencies($dependencies);

            return $reflector->newInstanceArgs($instances);
    }

    // 獲取參數(shù)的依賴
    protected function getDependencies($paramters) {
        $dependencies = [];
        foreach ($paramters as $paramter) {
            $dependencies[] = $this->make($paramter->getClass()->name);
        }

        return $dependencies;
    }
}

//實例化IoC容器
$ioc = new Ioc();
$ioc->bind('log','FileLog');
$ioc->bind('user','User');
$user = $ioc->make('user');
$user->login();

參考

1拦止、聊一聊PHP的依賴注入(DI) 和 控制反轉(IoC)
2、原則&模式|理解DIP糜颠、IoC汹族、DI以及IoC容器
3、Laravel 服務容器實例教程 —— 深入理解控制反轉(IoC)和依賴注入(DI)(推薦閱讀)
4括蝠、如何實現(xiàn) IoC 容器和服務提供者是什么概念(推薦閱讀)
5鞠抑、 [Laravel 5.8 文檔 ] 底層原理 —— 服務容器(推薦閱讀)
6、PHP反射機制實現(xiàn)自動依賴注入
7忌警、那些年搞不懂的高深術語——依賴倒置?控制反轉?依賴注入?面向接口編程
8搁拙、控制反轉(IOC)和依賴注入(DI)(推薦閱讀)
9、控制反轉和依賴注入的理解
10法绵、談談php里的IOC控制反轉箕速,DI依賴注入

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市朋譬,隨后出現(xiàn)的幾起案子盐茎,更是在濱河造成了極大的恐慌,老刑警劉巖徙赢,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件字柠,死亡現(xiàn)場離奇詭異,居然都是意外死亡狡赐,警方通過查閱死者的電腦和手機窑业,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枕屉,“玉大人常柄,你說我怎么就攤上這事。” “怎么了西潘?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵卷玉,是天一觀的道長。 經常有香客問我喷市,道長相种,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任东抹,我火速辦了婚禮蚂子,結果婚禮上,老公的妹妹穿的比我還像新娘缭黔。我一直安慰自己食茎,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布馏谨。 她就那樣靜靜地躺著别渔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惧互。 梳的紋絲不亂的頭發(fā)上哎媚,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音喊儡,去河邊找鬼拨与。 笑死,一個胖子當著我的面吹牛艾猜,可吹牛的內容都是我干的买喧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼匆赃,長吁一口氣:“原來是場噩夢啊……” “哼淤毛!你這毒婦竟也來了?” 一聲冷哼從身側響起算柳,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤低淡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后瞬项,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔗蹋,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年囱淋,在試婚紗的時候發(fā)現(xiàn)自己被綠了猪杭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡绎橘,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情称鳞,我是刑警寧澤涮较,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站冈止,受9級特大地震影響狂票,放射性物質發(fā)生泄漏。R本人自食惡果不足惜熙暴,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一闺属、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧周霉,春花似錦掂器、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至狞谱,卻和暖如春乃摹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跟衅。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工孵睬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伶跷。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓掰读,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撩穿。 傳聞我的和親對象是個殘疾皇子磷支,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容