依賴注入(DI)、控制反轉和容器

依賴注入(DI):將依賴對象注入到某對象,實現方式一般是容器。是控制反轉的具體實現方式
控制反轉(IoC):某對象獲得依賴對象的方式反轉了,由主動創建方式反轉成被動注入。是依賴注入的思想原理

場景:一個類的實例化需要依賴另外一個類的場景

注入方式以及優缺點

// 構造函數注入(構造函數傳參數)
// 屬性注入(設置屬性)
// 接口注入
// 容器注入

 

容器注入代碼:

class Container {

    protected $binds; // 綁定閉包
    protected $instances; // 綁定實例

    /**
     * 向容器中註冊服務(往盒子裏裝對象、或者創建對象的匿名函數)
     * 
     * @param $abstract 服務名稱
     * @param $conctete 服務體
     */
    public function bind($abstract, $concrete) {

        // 如果是個閉包則綁定到binds中
        if ($concrete instanceof Closure) {
            $this->binds[$abstract] = $concrete;
        } else {
            // 否則綁定到實例數組中
            $this->instances[$abstract] = $concrete;
        }
    }

    /**
     * 從容器中獲取服務(返回對象、或者執行匿名函數來返回對象)
     * 
     * @param $abstract 服務名稱
     * @param $params   實例化服務所需要傳遞的參數
     */
    public function make($abstract, $params = []) {

        // 如果是個實例就返回這個實例
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }
        
        array_unshift($params, $this);
        
        // 返回閉包執行結果
        return call_user_func_array($this->binds[$abstract], $params);
    }
}


class A1 {
    public $container;

    public function __construct()
    {
        $this->container = new Container();
    }

    public function addContainerData($key, $clourse)// 還可以用反射機制
    {
        $this->container->bind($key, $clourse);
    }

    public function select($key, $a)
    {
        $this->container->make($key)->select($a);
    }
}


class B1 {
    public function select($a) {
        echo "i am select {$a}\n";
    }
}

class C1 {
    public function select($a) {
        echo "i am select c1 {$a}\n";
    }
}

$A1 = new A1();
$A1->addContainerData('B1', function(){return new B1;});
$A1->addContainerData('C1', function(){return new C1;});
$A1->select('B1', '_hhhh');
$A1->select('C1', '_hhhh_c1');

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章