依賴注入(DI),控制反轉(zhuǎn)(IOC),依賴反轉(zhuǎn)(依賴倒置/DIP)

作為一個(gè)業(yè)余后端愛好者,雖然時(shí)不時(shí)會(huì)看spring和laravel的文檔,但是一直對(duì)依賴注入和控制反轉(zhuǎn)無法形成自己的理解。今天無意中又查找了些資料,有了新的理解。發(fā)現(xiàn)之前我想復(fù)雜了,因?yàn)閟pring和laravel對(duì)于依賴注入和控制反轉(zhuǎn)的設(shè)計(jì)已經(jīng)很完善,所以很難去抽絲剝繭依賴注入和控制反轉(zhuǎn)到底是什么東西。

正文開始
  • 假如我們現(xiàn)在要寫一個(gè)“人”類,我們?cè)凇叭恕鳖惱锩嬗幸粋€(gè) “生成人頭” 的方法, 下面是我們最初的樣子
class Person{
    String hairColor;
    String eyeColor;

    function generateHead(){
        hairColor = "green";
        eyeColor = "yellow";
    }
}
  • 后來我們通過簡單的面向?qū)ο笏季S,把它單獨(dú)交給一個(gè)頭類Head來完成
class Head{
    String hairColor;
    String eyeColor;
    __construct(String hColor, String eColor){
        hairColor = hColor;
        eyeColor = eColor;
    }
}

class Person{
    Head head;
    function generateHead(){
        head = new Head(hairColor: "green", eyeColor: "yellow");
    }
}
  • 但是我們的頭類依然在生成頭方法中去初始化,這很不靈活,所以我們?cè)谏深^的方法中設(shè)置一個(gè)“頭”這個(gè)參數(shù),允許從外部傳入“頭”
class Head{
    String hairColor;
    String eyeColor;
    __construct(String hColor, String eColor){
        hairColor = hColor;
        eyeColor = eColor;
    }
}

class Person{
    Head head;
    function generateHead(Head h){
        head = h;
    }
}

class PersonFactory{
    makePerson(){
        Head a = new Head(hairColor: "green", eyeColor: "yellow");
        Person p = new Person();
        p.generateHead(a);
    }
}

這時(shí)候已經(jīng)完成了控制反轉(zhuǎn),這里的控制指的是“初始化這個(gè)頭”的操作,反轉(zhuǎn)指的是“進(jìn)行這個(gè)操作的地點(diǎn)發(fā)生了變化”。
之前是在“人”類里面完成,現(xiàn)在是誰調(diào)用方法,誰完成,這就是控制反轉(zhuǎn)。
而方法傳參屬于依賴注入的其中一種方式,這里我們通過依賴注入實(shí)現(xiàn)了控制反轉(zhuǎn)。

QA
那我們實(shí)際在laravel或者spring框架中見到的實(shí)現(xiàn)方式為什么不是這個(gè)樣子呢?
因?yàn)榭蚣苤惺褂肐OC容器,實(shí)現(xiàn)了自動(dòng)依賴注入,所以不用再像我們這般去進(jìn)行手動(dòng)依賴注入的操作。

好了,到這里依賴注入和控制反轉(zhuǎn)就講完了,是不是很簡單的一個(gè)東西,其實(shí)這只是面向?qū)ο笏季S中,關(guān)于一個(gè)具體的實(shí)現(xiàn)細(xì)節(jié)的規(guī)定,平時(shí)可能大家都在使用這種規(guī)則,但當(dāng)專門拿出來說這是什么的時(shí)候,我們并不能把名字和操作細(xì)節(jié)對(duì)應(yīng)上,但其實(shí)是很簡單的一個(gè)概念,而我們很多時(shí)候稱這類操作為“組合”,“工廠模式”

現(xiàn)在新的挑戰(zhàn)出現(xiàn)了,當(dāng)我們要使用生成頭的時(shí)候,我們只能生成固定樣式地頭,假如有一天我們想讓人長一個(gè)“鐵頭”,“雞頭”,“烏龜頭”的時(shí)候,我們就需要去修改Person類,這是耦合的表現(xiàn),所以依賴反轉(zhuǎn)(依賴倒置/DIP)思維出現(xiàn)了

Interface Head{
    setColors(String hColor, String eColor);
}

class IronHead implement Head{
    String hairColor;
    String eyeColor;
    
    setColors(String hColor, String eColor){
        hairColor = hColor;
        eyeColor = eColor;
    }

   breakDoor(){
      
   }
}


class ChickenHead implement Head{
    String hairColor;
    String eyeColor;
    
    setColors(String hColor, String eColor){
        hairColor = hColor;
        eyeColor = eColor;
    }

   crow(){
      
   }
}


class TurtleHead implement Head{
    String hairColor;
    String eyeColor;
    
    setColors(String hColor, String eColor){
        hairColor = hColor;
        eyeColor = eColor;
    }

   makeYouCry(){
      
   }
}


class Person{
    Head head;
    function generateHead(Head h){
        head = h;
    }
}

class PersonFactory{
    makeIronPerson(){
        Head a = new IronHead(hairColor: "green", eyeColor: "yellow");
        Person p = new Person();
        p.generateHead(a);
    }

    makeChickenPerson(){
        Head a = new ChickenHead(hairColor: "yellow", eyeColor: "brown");
        Person p = new Person();
        p.generateHead(a);
    }

    makeTurtlePerson(){
        Head a = new TurtleHead(hairColor: "yellow", eyeColor: "brown");
        Person p = new Person();
        p.generateHead(a);
    }
}

好了,現(xiàn)在我們想創(chuàng)造不同頭的人,不再需要依賴修改Person類了,只需要添加一個(gè)想要的頭實(shí)現(xiàn)Head接口,然后直接組裝就可以了。這里我們選擇依賴抽象的接口Head,而不是具體的實(shí)現(xiàn),這就是依賴反轉(zhuǎn)(依賴倒置/DIP)。而我們通常稱為面向接口編程,抽象之類的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容