laravel的 容器container(ioc)

//ioc
//交通工具
interface Visit{
    public function go();
}
class Leg implements Visit{
    public function go(){
        echo 'legs';
    }
}
class Car implements Visit{
    public function go(){
        echo 'car';
    }
}
class Train implements Visit{
    public function go(){
        echo '火车';
    }
}
//旅游者类使用的佳通工具ioc容器
class Container{
    public $binding = [];
    public function bind($abstract, $concrete = null, $shared = false ){
        if(!$concrete instanceof Closure){
            //如果产生的不是闭包函数,则产生默认的闭包函数
            //$app->bind('Visit','Train');
            $concrete = $this->getClosure($abstract, $concrete);
        }
        /*
         *
         * 将回调 $concrete 闭包绑定到 $this->binding[$abstract]
         * */
        $this->binding[$abstract] = compact('concrete','shared');

    }
    //默认生成实例的回调函数
    public function getClosure($abstract, $concrete){
        //生成实例的回调函数,$c 一般为ioc容器对象 在调用回调生成实例时调用
        //buid 函数中 $concrete($this)

        return function ($c) use ($abstract, $concrete){
            $method = ($abstract === $concrete)?'build':'make';
            //调用的容器的build或者是make方法生成实例
            return $c->$method($concrete);
        };
    }
    //生成实例对象 首先解决接口和要实例化类之间的依赖关系
    public function make($abstract){
        //获取绑定的闭包函数
        $concrete = $this->getConcrete($abstract);
        //判断绑定的是不是闭包如果不是判断参数和获取的闭包是不是同一个,如果是同一个则表示需要实例化此对象
        if($this->isBuildable($concrete, $abstract)){
            $obj = $this->build($concrete);
        } else {
            $obj = $this->make($concrete);

        }
        return $obj;
    }
    //判断绑定的回调是否和传进来的是否相同
    public function isBuildable($concrete, $abstract){
        return $concrete === $abstract || $concrete instanceof Closure;
    }
    //获取绑定的闭包函数,如果没有绑定则返回参数
    public function getConcrete($abstract){
        if( !isset($this->binding[$abstract])){
            return $abstract;
        }
        return $this->binding[$abstract]['concrete'];
    }
    //实例化对象
    public function build($concrete){

        if($concrete instanceof Closure){
            //返回执行回调并把当前容器穿进去
            return $concrete($this);
        }
        //开始实例化此对象
        $reflector = new ReflectionClass($concrete);
        //如果此对象不能实例化报错
        if(!$reflector->isInstantiable()){
            echo 'target $concrete is not instantiable';
        }
        //获取对象的构造函数
        $constructor = $reflector->getConstructor();
        //如果对象没有构造函数则返回此对象
        if(is_null($constructor)){
            return new $concrete;
        }
        //获取构造函数的参数此类是 reflectionParameter对象构成的数组
        $dependencies = $constructor->getParameters();
        //获取依赖的类
        $instances = $this->getDependencies($dependencies);
        //创建一个新的类实例并把 获取到的依赖类的实例穿进去
        return $reflector->newInstanceArgs($instances);
    }
    //通过反射机制通过实例化对象的依赖
    public function getDependencies($parameters){
        $dependencies = [];
        //$parameters  ReflectionParameter类组成的数组
        foreach($parameters as $parameter){
            //获取参数类型(类就是一种类型);
            $dependency = $parameter->getClass();
            if(is_null($dependency)){
                $dependencies[] = null;
            }else {
                //获取已经注册的工具类实例
                $dependencies[] = $this->resolveClass($parameter);
            }
        }
        return (array) $dependencies;
    }
    public function resolveClass(ReflectionParameter $parameter){
        //获取参数类名
        return $this->make($parameter->getClass()->name);
    }

}
class Traveller{
    public $trafficTool;
    public function __construct(Visit $trafficTool)
    {
        $this->trafficTool = $trafficTool;
    }
    public function visitTibet(){
        $this->trafficTool->go();
    }
}
$app = new Container();
//完成容器的填充
//$app->bind('Visit',function(){
//    return new Train();
//});
$app->bind('Visit','Train');
//$app->bind('Visit','Car');
$app->bind('traveller','Traveller');
//print_r($app->binding);
//print_r($app->binding);
//通过容器实现依赖注入,完成类的实例化
$tra = $app->make('traveller');
$tra->visitTibet();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值