初識(shí)依賴注入

依賴注入,又稱(chēng)為控制反轉(zhuǎn)(Inversion of Control,英文縮寫(xiě)為IoC)是一個(gè)重要的面向?qū)ο缶幊痰姆▌t來(lái)削減計(jì)算機(jī)程序的耦合問(wèn)題,也是輕量級(jí)的Spring框架的核心。 控制反轉(zhuǎn)一般分為兩種類(lèi)型,依賴注入(Dependency Injection,簡(jiǎn)稱(chēng)DI)和依賴查找(Dependency Lookup)。依賴注入應(yīng)用比較廣泛。IoC 可以認(rèn)為是一種全新的設(shè)計(jì)模式

以上摘自百度百科,概念我們都知道是抽象的,難以理解的,要多在實(shí)際應(yīng)用去慢慢體會(huì)。舉個(gè)例子:

假如讓我們組建一支足球隊(duì)代表國(guó)家去參加世界杯,全球有這么多不同的國(guó)家,大家都想要參加比賽,那么首先,國(guó)家都有一個(gè)足球隊(duì)是不是,所以 國(guó)家依賴足球隊(duì)(團(tuán)隊(duì)),但是團(tuán)隊(duì)是由球員組成的是不是,所以團(tuán)隊(duì)依賴球員,有了這樣的關(guān)系,我們就可以建立一些遵循這些關(guān)系的類(lèi),很簡(jiǎn)單,核心的三個(gè)類(lèi)不能少,國(guó)家(Country),團(tuán)隊(duì)(Team),球員(Player),看代碼:

class Country {}

class Player {}

class Team {}

這些類(lèi)目前都是“空”的。讓我們想一想, 首先一個(gè) Country 得有個(gè)基本屬性 name 吧,比如就交 PRC,它依賴一個(gè) Team,

以對(duì)象作為參數(shù)傳遞

class Country 
{
    protected $team;
    protected $name;
    
    public function __construct(Team $team, $name = 'PRC')
    {
        $this->team = $team;
        $this->name = $name;
    }
}

這里,我們傳遞了兩個(gè)參數(shù)給構(gòu)造函數(shù),第一個(gè)參數(shù)就是使用了 Type Hinting,你可以稱(chēng)為類(lèi)型約束或類(lèi)型提示,來(lái)達(dá)到依賴注入。第二個(gè)參數(shù)就是簡(jiǎn)單的國(guó)家名稱(chēng),默認(rèn) PRC,到這里我們國(guó)家有了,因?yàn)橛忻至税。?依賴一個(gè)團(tuán)隊(duì) Team,但是 Team 還是空的,別急,讓我們給 Team 加點(diǎn)球員,沒(méi)有球員打 J8 球,還得是大牌,來(lái)定義一個(gè) join 方法:

class Team
{
    protected $players = [];
    
    public function __construct($players = [])
    {
        $this->players = $players;
    }
    
    public function join(Player $player)
    {
        $this->players[] = $player;
    }
    
    public function getPlayers()
    {
        return $this->players;
    } 
}

首先,我們定義了一個(gè) players 數(shù)組屬性用來(lái)存儲(chǔ)我們的球員,當(dāng)我們組建一個(gè)團(tuán)隊(duì)的時(shí)候,我們將自動(dòng)生成一個(gè) players 球員數(shù)組來(lái)控制加入團(tuán)隊(duì)的球員。在 join 方法中再一次以 Type Hinting 的方式傳遞一個(gè) Player 實(shí)例,只不過(guò)這一次實(shí)在普通方法里傳遞參數(shù)。最后用一個(gè)簡(jiǎn)單的獲取方法 getPlayers 來(lái)獲取我們加入到團(tuán)隊(duì)的球員,不然,這個(gè) Team 類(lèi),是不是就只進(jìn)不出了。接下來(lái),我們要給我們的球員取個(gè)名字,要不然都不知道有哪些大牌加入我們的 Team 呢:

class Player 
{
    protected $name;
    
    public function __construct($name)
    {
        $this->name = $name;
    }
}

好像到目前為止,依賴關(guān)系比較清晰了呢,但我們還有個(gè)小問(wèn)題,怎樣讓球員加入指定的國(guó)家呢?比如讓梅西為我大天朝效力。所以,很顯然國(guó)家必須有招募球員的能力:

發(fā)送消息

class Country
{
    protected $team;
    protected $name;
    
    public function __construct(Team $team, $name = 'PRC')
    {
        $this->team = $team;
        $this->name = $name;
    }
    
    public function recruit(Player $player)
    {
        $this->team->join($player);
    }
}

現(xiàn)在國(guó)家就用了招募球員到他們自己的團(tuán)隊(duì)里去了,這里我們可以將這個(gè)過(guò)程稱(chēng)為消息傳遞,message passing,方法的名稱(chēng)和輸入的參數(shù)被概念化為消息,看成類(lèi)與類(lèi),類(lèi)與對(duì)象,對(duì)象與對(duì)象之間的通信?;仡^再梳理一遍依賴關(guān)系,正如前面所說(shuō),國(guó)家依賴團(tuán)隊(duì),所以我們?cè)?Country 的構(gòu)造函數(shù)里傳遞了 Team 實(shí)例,那么實(shí)現(xiàn)這個(gè)過(guò)程,我們就應(yīng)該首先創(chuàng)建一個(gè) Team 實(shí)例,然后創(chuàng)建一個(gè) Country 實(shí)例,并傳遞 Team 實(shí)例給 Country

$team = new Team;
 
$china = new Country($team);

OK,接下來(lái)招募 PlayersTeam 中:

$player1 = new Player('梅西');
$china->recruit($player1);

然后,讓我們確認(rèn)下是不是梅西就到了國(guó)家隊(duì)了:

$team->getPlayers();


Array
(
    [0] => Player Object
        (
            [name:protected] => 梅西
        )
)

至此梅西已經(jīng)來(lái)到國(guó)家隊(duì)為我們征戰(zhàn)世界杯了,誒,不對(duì),足球不是一個(gè)人的游戲誒,梅西再牛逼沒(méi)有隊(duì)友怎么玩,繼續(xù)招募球員:

$player2 = new Player('C羅');
$player3 = new Player('內(nèi)馬爾');
$player4 = new Player('科比');
$player5 = new Player('詹姆斯');
…………
…………
 
$usa->recruit($player2);
$usa->recruit($player3);
$usa->recruit($player4);
$usa->recruit($player5);


$team->getplayers();

至此,新一屆的國(guó)家隊(duì)已經(jīng)成立,這陣容世界杯妥妥的。

總結(jié):

很簡(jiǎn)單的依賴注入的小示例,首先我們并沒(méi)有為了完成這個(gè)業(yè)務(wù)邏輯而創(chuàng)建一個(gè)大而全的類(lèi),試圖將所有的功能放在一個(gè)位置,而是分成很多業(yè)務(wù)邏輯比較單一和清晰的小類(lèi),即使這些類(lèi)是分開(kāi)的, 他們也能夠通過(guò) message passing 或彼此調(diào)用方法來(lái)通信。是不是感受到松耦合,容易維護(hù)的地方了,比如足球隊(duì)不要了,來(lái)個(gè)軍隊(duì)要開(kāi)戰(zhàn)了,招募點(diǎn)敢死隊(duì)是不是很方便?

最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,715評(píng)論 19 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,365評(píng)論 25 708
  • 為什么世界總不聽(tīng)話 人們總是希望這個(gè)世界按照自己的意愿運(yùn)轉(zhuǎn),希望身邊的任何人都聽(tīng)從自己的安排。事實(shí)上你會(huì)發(fā)現(xiàn),讓別...
    靜888閱讀 13,829評(píng)論 1 45
  • 綠茵圣騎士 正文卷 第一章 魔獸世界 一月份的英國(guó)倫敦,天氣格外的寒冷,漫天的雪花在寒風(fēng)中肆意地飛舞著,在幽深的街...
    Snow_DZG閱讀 2,505評(píng)論 1 6
  • 在我很小的時(shí)候,父母就是全部的世界,他們竭盡所能地守護(hù)著我,不讓我受到傷害,他們是我生活中不可或缺的一部分,我...
    彩虹赤子閱讀 1,173評(píng)論 3 2

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