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

猜你喜欢

转载自blog.csdn.net/weixin_38230961/article/details/106122047