依賴注入(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');