最新消息:欢迎加入小松的QQ群一起讨论一起学习,搜索页面修改成lua+ElasticSearch,使用php这个页面速度相对慢一点,优化之后速度杠杠的,如有问题请加群联系我

laravel Ioc(控制反转)和Di(依赖注入)

PHP 327浏览 0评论

php设计模式中Ioc(控制反转)和Di(依赖注入)主要是为了程序的解耦用的,网上找了一下资料,文章都是复制来复制去,没有什么价值,感觉最有价值的文章
推荐文章 http://www.51glacier.com/blog/Container.html,这篇文章讲的还是挺清楚的
下面的laravel中的使用
Laravel容器的简化版,中间加了注释,不懂可以加群讨论

<?php
interface Visit{
    public function go();
}
class Leg implements Visit{
    public function go(){
        echo 'walt to Tibet!!!';
    }
}
class Car implements Visit{
    public function go(){
        echo "drive car to Tibet!!!";
    }
}
class Train implements Visit{
    public function go(){
        echo "go to Tibet by train!!!";
    }
}
class Container{
    protected $bindings=[];
    //全局变量保持闭包函数
    public function bind($abstract,$concrete=null,$shared=false){
        //如果这个不是一个闭包函数,就用getClosure创建一个闭包函数
        if(!$concrete instanceof Closure){
            $concrete=$this->getClosure($abstract,$concrete);
        }
        //保存成多位数组
        $this->bindings[$abstract]=compact('concrete','shared');
    }
    //生成一个闭包函数
    protected function getClosure($abstract,$concrete){
        //这里的$c对应build方法$concrete($this);中的this
        return function($c) use($abstract,$concrete){
            $method=($abstract==$concrete)?'build':'make';
            return $c->$method($concrete);
        };
    }
    public function make($abstract){
        $concrete=$this->getConcrete($abstract);
        //判断是否是一个闭包函数
        if($this->isBuildable($concrete,$abstract)){
            //是一个闭包函数就实例化
            $object=$this->build($concrete);
        }else{
            $object=$this->make($concrete);
        }
        return $object;
    }
    //判断是否是一个闭包函数
    protected function isBuildable($concrete,$abstract){
        return $concrete===$abstract||$concrete instanceof Closure;
    }
    //判断全局变量$this->bindings里有没有注入这个类
    protected function getConcrete($abstract){
        if(!isset($this->bindings[$abstract])){
            return $abstract;
        }
        return $this->bindings[$abstract]['concrete'];
    }
    //用反射的方式实例化类
    public function build($concrete){
        //如果是一个闭包函数就直接返回
        if($concrete instanceof Closure){
            return $concrete($this);
        }
        //反射实例化类
        $reflector=new ReflectionClass($concrete);
        //反射的方式判断类是否可以实例化
        if(!$reflector->isInstantiable()){
            echo $message="Target [$concrete] is not instantiable.";
        }
        //判断有没有构造函数
        $constructor=$reflector->getConstructor();
        //如果没有构造函数就直接实例化
        if(is_null($constructor)){
            return new $concrete;
        }
        //反射构造函数的参数
        $dependencies=$constructor->getParameters();
        $instances=$this->getDependencies($dependencies);
        return $reflector->newInstanceArgs($instances);
    }
    protected function getDependencies($parameters){
        $dependencies=[];
        foreach($parameters as $parameter){
            //反射方式参数的接口比如Traveller类中的$trafficTool的变量必须是Visit这个类型的
            $dependency=$parameter->getClass();
            if(is_null($dependency)){
                $dependencies[]=NULL;
            }else{
                //如果要有限制的参数,在注入这个类
                $dependencies[]=$this->resolveClass($parameter);
            }
        }
        return (array)$dependencies;
    }
    protected function resolveClass(ReflectionParameter $parameter){
        return $this->make($parameter->getClass()->name);
    }
}
class Traveller{
    protected $trafficTool;
    public function __construct(Visit $trafficTool)
    {
        $this->trafficTool=$trafficTool;
    }
    public function visitTibet(){
        $this->trafficTool->go();
    }
}
$app=new Container();
$app->bind("Visit","Train");
$app->bind("traveller","Traveller");
$tra=$app->make("traveller");
$tra->visitTibet();

容器是laravel的核心知识点,看懂这一块内容感觉又牛逼了点
github: https://github.com/QiuCarson/Laravel-Container

QQ交流群:136351212(满) 455721967

如无特别说明,本站文章皆为原创,若要转载,务必请注明以下原文信息:
转载保留版权:小松博客» laravel Ioc(控制反转)和Di(依赖注入)
本文链接地址:https://www.phpsong.com/3031.html

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
木有头像就木有JJ!点这里按步骤申请Gravatar头像吧!