php設(shè)計(jì)模式 依賴(lài)注入和控制反轉(zhuǎn)

依賴(lài)注入和控制反轉(zhuǎn)在現(xiàn)如今的主流框架中經(jīng)常可以看到,主要是用于解決程序的松耦合,便于程序的協(xié)調(diào)開(kāi)發(fā)和管理。

DI——Dependency Injection 依賴(lài)注入

IoC——Inversion of Control 控制反轉(zhuǎn)

當(dāng)一個(gè)類(lèi)的實(shí)例需要另一個(gè)類(lèi)的實(shí)例協(xié)助時(shí),在傳統(tǒng)的程序設(shè)計(jì)過(guò)程中,通常由調(diào)用者來(lái)創(chuàng)建被調(diào)用者的實(shí)例。而采用依賴(lài)注入的方式,創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來(lái)完成,因此叫控制反轉(zhuǎn),創(chuàng)建被調(diào)用者的實(shí)例的工作由IOC容器來(lái)完成,然后注入調(diào)用者,因此也稱(chēng)為依賴(lài)注入。

控制反轉(zhuǎn)(Inversion of Control):當(dāng)調(diào)用者需要被調(diào)用者的協(xié)助時(shí),在傳統(tǒng)的程序設(shè)計(jì)過(guò)程中,通常由調(diào)用者來(lái)創(chuàng)建被調(diào)用者的實(shí)例,但在這里,創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來(lái)完成,而是將被調(diào)用者的創(chuàng)建移到調(diào)用者的外部,從而反轉(zhuǎn)被調(diào)用者的創(chuàng)建,消除了調(diào)用者對(duì)被調(diào)用者創(chuàng)建的控制,因此稱(chēng)為控制反轉(zhuǎn)。

依賴(lài)注入(Dependency Injection):要實(shí)現(xiàn)控制反轉(zhuǎn),解決方案是將創(chuàng)建被調(diào)用者實(shí)例的工作交由IoC容器來(lái)完成,然后在調(diào)用者中注入被調(diào)用者(通過(guò)構(gòu)造器/方法注入實(shí)現(xiàn)),這樣我們就實(shí)現(xiàn)了調(diào)用者與被調(diào)用者的解耦,該過(guò)程被稱(chēng)為依賴(lài)注入。依賴(lài)注入是控制反轉(zhuǎn)的一種實(shí)現(xiàn)方式。常見(jiàn)注入方式有三種:setter、constructor injection、property injection。

比如我們寫(xiě)一個(gè)file的緩存類(lèi),類(lèi)user需要用到這個(gè)緩存類(lèi) 傳統(tǒng)的調(diào)用方式是在調(diào)用者中實(shí)例化被調(diào)用者

class fileCache{
    /**
     * 設(shè)置緩存
     * @param $name
     * @param $value
     */
    public function set($name ,$value){
        //TODO
    }

    /**
     * 刪除緩存
     * @param $name
     */
    public function delete($name){
        //TODO
    }

    /**
     * 獲取緩存數(shù)據(jù)
     * @param $name
     */
    public function get($name){
        //TODO
    }
}

class User {
    protected $cache;

    public function __construct() {
        $this->cache = new fileCache();
    }

    public function getUser(){
        return $this->cache->get("user");
    }


}


$user = new User();

$user->getUser();

一旦平臺(tái)或者環(huán)境發(fā)生變化,我們不用file來(lái)做為緩存,而是用redis做緩存,那相應(yīng)調(diào)用類(lèi)User就需要做出修改。程序不應(yīng)該依賴(lài)于具體的實(shí)現(xiàn),而是要依賴(lài)抽像的接口

class fileCache implements Cache{

    public function set($name)
    {
        //TODO
    }

    public function get($name)
    {
        //TODO
    }

    public function delete($name)
    {
        //TODO
    }

}


class redisCache implements Cache{

    public function set($name)
    {
        //TODO
    }

    public function get($name)
    {
        //TODO
    }

    public function delete($name)
    {
        //TODO
    }

}

構(gòu)造器注入

class User{

    protected $cache ;

    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }

    public function getUser()
    {
        return $this->cache->get('user');
    }


}

$redis = new redisCache();
$user = new User($redis);
$user->getUser();

$file = new fileCache();
$user = new User($file);
$user->getUser();

setter注入

class User{

    protected $cache ;

    public function  setCache( Cache $cache)
    {
        $this->cache = $cache;
    }

    public function getUser()
    {
        return $this->cache->get('user');
    }


}


$redis = new redisCache();
$user = new User();
$user->setCache($redis);
$user->getUser();

$file = new fileCache();
$user = new User();
$user->setCache($file);
$user->getUser();

但是這樣的注入還會(huì)產(chǎn)生一個(gè)問(wèn)題,當(dāng)調(diào)用類(lèi)依賴(lài)于多個(gè)外部類(lèi)時(shí),我們就需要不斷的寫(xiě)set

$user = new User();

$user->setDb($db);//注入db連接

$user->setCache($file);//注入緩存處理類(lèi)
#.....

如果引入的外部類(lèi)很多時(shí),就會(huì)變得十分繁瑣。這就引入另一個(gè)概念容器又叫做IoC容器、DI容器。
這里我們引入一個(gè)約定:在User類(lèi)的構(gòu)造函數(shù)里傳入一個(gè)名為Di $di的參數(shù),如下:

class Di{
    protected $_objects = [];


    public function set($name, $object)
    {

        $this->_objects[$name] = $object;

    }
    public function get($name) {
        return $this->_objects[$name];
    }
}


class User {

    private $_di;

    function __construct(Di &$di)
    {

        $this->_di = $di;

    }

    //通過(guò)di容器獲取db實(shí)例

    public function getUser()
    {
        return $this->_di->get('cache')->get('User');
    }

}

$di = new Di();

$cache  = new fileCache();

$di->set("cache",$cache);

$user = new User($di);

$user->getUser();
?著作權(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ù)。

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