淺談控制反轉(zhuǎn)與依賴(lài)注入

注:本文轉(zhuǎn)載于:https://zhuanlan.zhihu.com/p/33492169

第一章:小明和他的手機(jī)

從前有個(gè)人叫小明

小明有三大愛(ài)好,抽煙,喝酒…… 咳咳,不好意思,走錯(cuò)片場(chǎng)了。應(yīng)該是逛知乎、玩王者農(nóng)藥和搶微信紅包
小明的三大愛(ài)好

我們用一段簡(jiǎn)單的偽代碼,來(lái)制造一個(gè)這樣的小明

class Ming extends Person
{
    private $_name;

    private $_age;

    function read()
    {
        //逛知乎
    }

    function  play()
    {
        //玩農(nóng)藥
    }

    function  grab()
    {
        //搶紅包
    }

}

但是,小明作為一個(gè)人類(lèi),沒(méi)有辦法僅靠自己就能實(shí)現(xiàn)以上的功能,他必須依賴(lài)一部手機(jī),所以他買(mǎi)了一臺(tái)iphone6,接下來(lái)我們來(lái)制造一個(gè)iphone6

class iPhone6 extends Iphone
{
    function read($user="某人")
    {
        echo $user."打開(kāi)了知乎然后編了一個(gè)故事 \n";
    }

    function play($user="某人")
    {
        echo $user."打開(kāi)了王者農(nóng)藥并送起了人頭 \n";
    }

    function grab($user="某人")
    {
        echo $user."開(kāi)始搶紅包卻只搶不發(fā) \n";
    }
}

小明非常珍惜自己的新手機(jī),每天把它牢牢控制在手心里,所以小明變成了這個(gè)樣子

class Ming extends Person
{
    private $_name;

    private $_age;

    public function  __construct()
    {
        $this->_name = '小明';
        $this->_age = 26;
    }

    function read()
    {
        //……  省略若干代碼
        (new iPhone6())->read($this->_name); //逛知乎
    }

    function  play()
    {
        //……  省略若干代碼
        (new iPhone6())->play($this->_name);//玩農(nóng)藥

    }

    function  grab()
    {
        //……  省略若干代碼
        (new iPhone6())->grab($this->_name);//搶紅包

    }

}

今天是周六,小明不用上班,于是他起床,并依次逛起了知乎,玩王者農(nóng)藥,并搶了個(gè)紅包。

$ming = new Ming();  //小明起床
$ming->read();
$ming->play();
$ming->grab();

這個(gè)時(shí)候,我們可以在命令行里看到輸出如下

小明打開(kāi)了知乎然后編了一個(gè)故事 
小明打開(kāi)了王者農(nóng)藥并送起了人頭 
小明開(kāi)始搶紅包卻只搶不發(fā)

這一天,小明過(guò)得很充實(shí),他覺(jué)得自己是世界上最幸福的人。

第二章: 小明的快樂(lè)與憂(yōu)傷

小明和他的手機(jī)曾一起度過(guò)了一段美好的時(shí)光,一到空閑時(shí)刻,他就抱著手機(jī),逛知乎,刷微博,玩游戲,他覺(jué)得自己根本不需要女朋友,只要有手機(jī)在身邊,就滿(mǎn)足了。

可誰(shuí)能想到,一次次地系統(tǒng)更新徹底打碎了他的夢(mèng)想,他的手機(jī)變得越來(lái)越卡頓,電池的使用壽命也越來(lái)越短,一直到某一天的寒風(fēng)中,他的手機(jī)終于耐不住寒冷,頭也不回地關(guān)了機(jī)。

小明很憂(yōu)傷,他意識(shí)到,自己要換手機(jī)了。

為了能獲得更好的使用體驗(yàn),小明一咬牙,剁手了一臺(tái)iphoneX,這部手機(jī)鈴聲很大,電量很足,還能雙卡雙待,小明很喜歡,但是他遇到一個(gè)問(wèn)題,就是他之前過(guò)度依賴(lài)了原來(lái)那一部iPhone6,他們之間已經(jīng)深深耦合在一起了,如果要換手機(jī),他就要拿起刀來(lái)改造自己,把自己體內(nèi)所有方法中的iphone6 都換成 iphoneX。
漫長(zhǎng)的改造過(guò)程

經(jīng)歷了漫長(zhǎng)的改造過(guò)程,小明終于把代碼中的 iphone6 全部換成了 iphoneX。雖然很辛苦,但是小明覺(jué)得他是快樂(lè)的。

于是小明開(kāi)開(kāi)心心地帶著手機(jī)去上班了,并在回來(lái)的路上被小偷偷走了。為了應(yīng)急,小明只好重新使用那部剛剛被遺棄的iphone6,但是一想到那漫長(zhǎng)的改造過(guò)程,小明的心里就說(shuō)不出的委屈,他覺(jué)得自己過(guò)于依賴(lài)手機(jī)了,為什么每次手機(jī)出什么問(wèn)題他都要去改造他自己,這不僅僅是過(guò)度耦合,簡(jiǎn)直是本末倒置,他向天空大喊,我不要再控制我的手機(jī)了。

天空中的造物主,也就是作為程序員的我,聽(tīng)到了他的吶喊,我告訴他,你不用再控制你的手機(jī)了,交給我來(lái)管理,把控制權(quán)交給我。這就叫做控制反轉(zhuǎn)。

第三章:造物主的智慧

小明聽(tīng)到了我的話(huà),他既高興,又有一點(diǎn)害怕,他跪下來(lái)磕了幾個(gè)頭,虔誠(chéng)地說(shuō)到:“原來(lái)您就是傳說(shuō)中的造物主,巴格梅克上神。我聽(tīng)到您剛剛說(shuō)了 控制反轉(zhuǎn) 四個(gè)字,就是把手機(jī)的控制權(quán)從我的手里交給你,但這只是您的想法,是一種思想罷了,要用什么辦法才能實(shí)現(xiàn)控制反轉(zhuǎn),又可以讓我繼續(xù)使用手機(jī)呢?”

“呵“,身為造物主的我在表現(xiàn)完不屑以后,扔下了四個(gè)大字,“依賴(lài)注入!”

接下來(lái),偉大的我開(kāi)始對(duì)小明進(jìn)行慘無(wú)人道的改造,如下

class Ming extends Person
{
    private $_name;

    private $_age;

    private $_phone; //將手機(jī)作為自己的成員變量

    public function  __construct($phone)
    {
        $this->_name = '小明';
        $this->_age = 26;
        $this->_phone = $phone;
        echo "小明起床了 \n";
    }

    function read()
    {
        //……  省略若干代碼
        $this->_phone->read($this->_name); //逛知乎
    }

    function  play()
    {
        //……  省略若干代碼
        $this->_phone->play($this->_name);//玩農(nóng)藥

    }

    function  grab()
    {
        //……  省略若干代碼
        $this->_phone->grab($this->_name);//搶紅包

    }

}

接下來(lái),我們來(lái)模擬運(yùn)行小明的一天

$phone = new IphoneX(); //創(chuàng)建一個(gè)iphoneX的實(shí)例
if($phone->isBroken()){//如果iphone不可用,則使用舊版手機(jī)
    $phone = new Iphone6();
}
$ming = new Ming($phone);//小明不用關(guān)心是什么手機(jī),他只要玩就行了。
$ming->read();
$ming->play();
$ming->grab();

我們先看一下iphoneX 是否可以使用,如果不可以使用,則直接換成iphone6,然后喚醒小明,并把手機(jī)塞到他的手里,換句話(huà)說(shuō),把他所依賴(lài)的手機(jī)直接注入到他的身上,他不需要關(guān)心自己拿的是什么手機(jī),他只要直接使用就可以了。

這就是依賴(lài)注入。

第四章:小明的感悟

小明的生活開(kāi)始變得簡(jiǎn)單了起來(lái),而他把省出來(lái)的時(shí)間都用來(lái)寫(xiě)筆記了,他在筆記本上這樣寫(xiě)到

我曾經(jīng)有很強(qiáng)的控制欲,過(guò)度依賴(lài)于我的手機(jī),導(dǎo)致我和手機(jī)之間耦合程度太高,只要手機(jī)出現(xiàn)一點(diǎn)點(diǎn)問(wèn)題,我都要改造我自己,這實(shí)在是既浪費(fèi)時(shí)間又容易出問(wèn)題。自從我把控制權(quán)交給了造物主,他每天在喚醒我以前,就已經(jīng)替我選好了手機(jī),我只要按照平時(shí)一樣玩手機(jī)就可以了,根本不用關(guān)心是什么手機(jī)。即便手機(jī)出了問(wèn)題,也可以由造物主直接搞定,不需要再改造我自己了,我現(xiàn)在買(mǎi)了七部手機(jī),都交給了造物主,每天換一部,美滋滋!
我也從其中獲得了這樣的感悟: 如果一個(gè)類(lèi)A 的功能實(shí)現(xiàn)需要借助于類(lèi)B,那么就稱(chēng)類(lèi)B是類(lèi)A的依賴(lài),如果在類(lèi)A的內(nèi)部去實(shí)例化類(lèi)B,那么兩者之間會(huì)出現(xiàn)較高的耦合,一旦類(lèi)B出現(xiàn)了問(wèn)題,類(lèi)A也需要進(jìn)行改造,如果這樣的情況較多,每個(gè)類(lèi)之間都有很多依賴(lài),那么就會(huì)出現(xiàn)牽一發(fā)而動(dòng)全身的情況,程序會(huì)極難維護(hù),并且很容易出現(xiàn)問(wèn)題。要解決這個(gè)問(wèn)題,就要把A類(lèi)對(duì)B類(lèi)的控制權(quán)抽離出來(lái),交給一個(gè)第三方去做,把控制權(quán)反轉(zhuǎn)給第三方,就稱(chēng)作控制反轉(zhuǎn)(IOC Inversion Of Control)。控制反轉(zhuǎn)是一種思想,是能夠解決問(wèn)題的一種可能的結(jié)果,而依賴(lài)注入(Dependency Injection)就是其最典型的實(shí)現(xiàn)方法。由第三方(我們稱(chēng)作IOC容器)來(lái)控制依賴(lài),把他通過(guò)構(gòu)造函數(shù)、屬性或者工廠(chǎng)模式等方法,注入到類(lèi)A內(nèi),這樣就極大程度的對(duì)類(lèi)A和類(lèi)B進(jìn)行了解耦

最后

以上就是對(duì)控制反轉(zhuǎn)和依賴(lài)注入的理解和總結(jié)啦!

原文地址:https://zhuanlan.zhihu.com/p/33492169

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,481評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,241評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,939評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,697評(píng)論 6 409
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,182評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,406評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,933評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,772評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,973評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,638評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,866評(píng)論 1 285
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,644評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,953評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容