溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PHP的依賴注入容器是什么東西?

發(fā)布時(shí)間:2020-05-21 22:41:50 來源:億速云 閱讀:327 作者:鴿子 欄目:編程語言

依賴注入容器理解

耦合

一個(gè)好的代碼結(jié)構(gòu)設(shè)計(jì)一定是松耦合的,這也是很多通用設(shè)計(jì)模式的宗旨,就是把分散在各處的同一個(gè)功能的代碼匯聚到一起,形成一個(gè)模塊,然后在不同模塊之間通過一些細(xì)小的、明確的渠道進(jìn)行溝通。

在實(shí)踐中,不同功能和模塊之間的互相依賴是不可避免的,而如何處理好這些依賴之間的關(guān)系則是代碼結(jié)構(gòu)能否變得美好的關(guān)鍵。

<?php
class User
{
    public function register($user)
    {
        // 注冊(cè)操作
        ...
 
        // 發(fā)送確認(rèn)郵件
        $notify = new Notify();
        $notify->sendEmail('register', $user);
    }
}
 
class Notify
{
    public function sendEmail($type, $data)
    {
        switch $type {
            case 'register':
                // 發(fā)送注冊(cè)確認(rèn)郵件
                $email = new Email($type);
                $email->send($data);
            ...
        }
    }
}
 
class Email
{
    public function send($data)
    {
        // 發(fā)送郵件
    }
}

上述代碼中,三個(gè)類之間逐層依賴,三個(gè)類實(shí)例化的順序是 User -> Notify -> Email

也就是說我先實(shí)例化User類,可能執(zhí)行了一些代碼之后再去實(shí)例化我需要的其他類,比如Notify,以此類推。

這種依賴會(huì)讓我們不得不為了得到需要的依賴而去做的一些準(zhǔn)備工作,有時(shí)候可能一個(gè)new操作還不夠。而這部分工作就是所說的耦合,他會(huì)讓一個(gè)獨(dú)立功能的類不得不去關(guān)心一些和自己的主體功能沒什么關(guān)系的操作。

解除一個(gè)類對(duì)其他類的依賴

要解決這個(gè)問題也很簡單,我可以先實(shí)例化好Email類,然后再實(shí)例化Notify,然后把Email對(duì)象作為參數(shù)傳給Notify,最后實(shí)例化User類,然后把Notify傳進(jìn)去。這就是所謂的依賴注入,可以看到這個(gè)過程中類實(shí)例化的順序完全反過來了,先實(shí)例化被依賴的對(duì)象,而不是先實(shí)例化最終需要的對(duì)象,這是控制反轉(zhuǎn)。

代碼如下:

<?php
$email = new Email();
$notify = new Notify($email);
$user = new User($notify);

可以通過構(gòu)造函數(shù)來注入需要的依賴,也可以用一些其他的方法。

用容器托管依賴

那又有新的問題,例子中只有三個(gè)類還好,那如果這個(gè)User類依賴Notify來發(fā)郵件,依賴Model來存數(shù)據(jù)庫,依賴redis來緩存,這樣固然把依賴關(guān)系轉(zhuǎn)移到了類的外部,但還是會(huì)導(dǎo)致我只想實(shí)例化一下User的時(shí)候,卻要手動(dòng)做很多的準(zhǔn)備工作,會(huì)讓代碼混亂。所以這個(gè)時(shí)候需要一個(gè)容器。而這個(gè)容器的作用就是替我來管理這些依賴。

<?php
// 容器
class Container implements ArrayAccess
{
    protected $values = [];
 
    public function offsetGet($offset) 
    {
        return $this->values[$offset]($this);
    }
 
    public function offsetSet($offset, $value) 
    {
        $this->values[$offset] = $value;
    }
}

在程序啟動(dòng)的時(shí)候,我們可以在一個(gè)地方統(tǒng)一的注冊(cè)好一系列的基礎(chǔ)服務(wù)。

<?php
$container = new Container();
 
$container['notify'] = function($c) {
    return new Notify();
};
 
$container['email'] = function($c) {
    return new Email();
};

就會(huì)變成這樣

<?php
class User
{
    public function register($user)
    {
        // 注冊(cè)操作
        ...
 
        // 發(fā)送確認(rèn)郵件
        $container('notify')->sendEmail('register', $user);
    }
}
 
class Notify
{
    public function sendEmail($type, $data)
    {
        switch $type {
            case 'register':
                // 發(fā)送注冊(cè)確認(rèn)郵件
                $email = $container['email'];
                $email->send($data);
            ...
        }
    }
}
 
class Email
{
    public function send($data)
    {
        // 發(fā)送郵件
    }
}

就是當(dāng)User需要Notify的時(shí)候,會(huì)去向容器要這個(gè)類的對(duì)象,那至于Notify再依賴什么其他的東西,我就不用管了,因?yàn)镹otify也會(huì)去向容器要它自己需要的依賴。所有這些依賴關(guān)系的處理就完全托管給容器了,我們既不需要去關(guān)心依賴之間的層次關(guān)系,也避免了依賴之間的耦合。

需要注意的是,依賴注入容器一般只接受一個(gè)匿名函數(shù),而不是一個(gè)實(shí)例化好的對(duì)象,匿名函數(shù)會(huì)告訴容器怎樣去獲得一個(gè)對(duì)象,這樣可以使得一個(gè)服務(wù)在被需要的時(shí)候才會(huì)去實(shí)例化

以上就是通俗易懂理解PHP依賴注入容器的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注億速云其它相關(guān)文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI