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