关于IoC容器的理解

<?php
class Container{
    protected $instance; 
    protected $binds;

    /**
     * 绑定一个抽象类
     * @param $abstract
     * @param $concrete
     */

    public function bind($abstract,$concrete){

        if ($concrete instanceof Closure){
            $this->binds[$abstract] = $concrete;
        }else{
            $this->instance[$abstract] = $concrete;
        }
//        var_dump($this);
        echo "<br />";
    }

    /**
     * 制造一个类
     * @param $abstract
     * @param array $parameter
     * @return mixed
     */

    public function make($abstract,$parameter = []){
        if (isset($this->instance[$abstract])){ // 检测变量是否已设置并且非 NULL
            return $this->instance[$abstract]; // 如果已经设置了则直接返回
        }
        echo "<pre>";
        var_dump($parameter);
        echo "</pre>";
        echo "<br />";
        echo "<br />";
        echo "<br />";
        echo "<br />";
        array_unshift($parameter,$this); //在数组开头插入一个或多个单元 方便在下一步调用的时候 将之前需要实现的依赖,进行提前处理
        echo "<pre>";
        var_dump($parameter);
        var_dump($this->binds[$abstract]);exit;
        echo "</pre>";

        return call_user_func_array($this->binds[$abstract],$parameter); //调用回调函数,并把一个数组参数作为回调函数的参数
    }
}

// 创建一个容器(后面称作超级工厂)
$container = new Container;

// 向该 超级工厂 添加 超人 的生产脚本
$container->bind('superman', function($container, $moduleName) {
    return new Superman($container->make($moduleName));
});

// 向该 超级工厂 添加 超能力模组 的生产脚本
$container->bind('xpower', function($container) {
    return new XPower;
});

//var_dump(function($container) {
//    return new XPower;
//});

$container->make("superman",['xpower']);

//首先在工厂的基础上增加一个容器 这个容器用来存储要实现的类 要是那些类当然先要告诉这个容器 也就是提前在容器中注册。
//通过bind数组的形式 将实现类的匿名函数以key (类名) value(实现方法)注册到容器中
//在注册的时候需要判断一下 如果是一个继承自匿名类则直接绑定 如果不是匿名类则使用 instances(模块) 变量 存储属性 用于实现一组依赖
//绑定成功后如果在使用到的地方在进行生产,彻底将模块和实现分离。
//在需要的时候就进行make,方法接收要是实现的类和模块参数,通过array_unshift调整call_user_func_array的参数顺序 将需要模块提前执行 最后执行在将模块注入到实现的类中

参考 https://www.insp.top/learn-laravel-container

posted @ 2020-11-21 11:11  青柚  阅读(154)  评论(0编辑  收藏  举报