资讯专栏INFORMATION COLUMN

实现一个简单的di容器

clasnake / 728人阅读

摘要:下面的代码是我实现的一个简单的容器,很多地方处理并不是很好,但是应该已经足够了。这个变量保存,是名字实例的映射单例一开始是受到的影响,所以写了一个函数,看完的容器实现,印象之中,和来回变换。

之前看了好多框架,laravel,thinkphp,yii等等。基本上都使用了容器。对于我而言,虽然看懂了laravel是怎么写的,但是如果自己不去尝试一下,始终觉得不会这个东西。

下面的代码是我实现的一个简单的容器,很多地方处理并不是很好,但是应该已经足够了。

实例的映射
    private $binds = [];


    public static $instance = null;

    /**
     * 单例
     */
    public static function getInstance(){
        if(static::$instance == null){
            static::$instance = new static();
            return static::$instance ;
        }
        return static::$instance;
    }

    /**
     * 一开始是受到laravel的影响,所以写了一个bind函数,
     * 看完laravel的容器实现,印象之中,$concrete和$abstract来回变换。
     * 下面的代码有点像thinkphp的里面的实现,好理解一点
     */
    public static function bind($name,$class = null){
        if($class instanceof Closure){
            static::getInstance()->binds[$name] = $class;
        }else if(is_object($class)){
            static::getInstance()->binds[$name] = $class;
        }else{
            //在这里开始make一个数组,laravel好像是make和build分开的。
            static::getInstance()->make($name);
        }
        
    }

    /**
     * 核心是make方法了
     */
    public static function get($name){
        return static::getInstance()->make($name);
    }

    /**
     * 核心make方法
     */
    public function make($name){
        try{
            //根据类名去查找$this->binds实例是否已经存在,如果存在就直接返回
            if(array_key_exists($name,$this->binds)){
                return $this->binds[$name];
            }
            //根据类名得到它的反射类
            $reflectClass = new ReflectionClass($name);
            //利用反射类
            $constructor = $reflectClass->getConstructor();
            //如果没有构造器的话,就直接去实例化它
            $params = [];
            if(!is_null($constructor)){
                //获取构造器中的方法
                $constructorParams = $constructor->getParameters();
                // var_dump($constructorParams);
                //保存构造器的参数
                foreach($constructorParams as $constructorParam){
                    //这个地方主要是判断参数是否是类,如果是就递归的构造它,不是就简单的添加到$this->params中
                    if(!is_null($constructorParam->getType())){
                        $params[] =$this->make($constructorParam->name,$constructorParam->name);
                    }else{
                        $params[] = $constructorParam->name;
                    }
                }
            }
            //在这个地方构造实例
            $class = $reflectClass->newInstanceArgs($params);
            //绑定
            $this->binds[$name] = $class;
            return $class;
        }catch(ReflectionException $e){
            echo $e->getMessage();
        }
    }

    private function __construct(){}
    private function __clone(){}

}
?>

下面是我的测试文件了,

name;
    }

    public function sayDI2Name(DI2 $di2){
        //如果这么写的,di2方法会先于前面的字符串打印出来
        // echo "form Test say di2 name: ".$di2->sayName();
        echo "form Test say di2 name: ";
        echo $di2->sayName();
    }
}

class DI{
    private $name = "DI";
    public function __construct(DI2 $di2){}
    public function sayName(){
        echo $this->name;
    }    
}

class DI2{
    private $name = "DI2";
    public function __construct(){}
    
    public function sayName(){
        echo $this->name;
    }   
}

class DI3{
    private $name = "DI3";
    public function __construct(){}
    
    public function sayName(){
        echo $this->name;
    }   
}

class DI4{
    private $name = "DI4";
    public function __construct(){}
    
    public function sayName(){
        echo $this->name;
    }   
}

//要不要无所谓了
// Container::bind("test","Test"); 
$test = Container::get("test");
$test->sayName();
echo "
";
$test->sayDI2Name(new DI2());
echo "
";

$di = Container::get("di");
$di->sayName();

echo "
";
$di2 = Container::get("di2");
$di2->sayName();

echo "
";
$di3 = new DI3();
Container::get("di3",$di3)->sayName();
echo "
";
$di4 = function(){
    return new DI4();
};

Container::get("di4",$di4)->sayName();
echo "
";


?>

最后的结果如下

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/30963.html

相关文章

  • Yii源码解读-依赖注入(容器

    摘要:在中使用解耦,有两种注入方式构造函数注入属性注入。对象的实例化解析依赖信息该方法实质上就是通过的反射机制,通过类的构造函数的参数分析他所依赖的单元。 有关概念 依赖倒置原则(Dependence Inversion Principle, DIP) 传统软件设计中,上层代码依赖于下层代码,当下层出现变动时,上层也要相应变化。 DIP的核心思想是:上层定义接口,下层实现这个接口,从而使的下...

    Prasanta 评论0 收藏0
  • PHP程序员如何理解IoC/DI

    摘要:依赖注入容器管理应用程序中的全局对象包括实例化处理依赖关系。为了解决这样的问题,我们再次回到全局注册表创建组件。参考文章程序员如何理解依赖注入容器补充很多代码背后,都是某种哲学思想的体现。 思想 思想是解决问题的根本思想必须转换成习惯构建一套完整的思想体系是开发能力成熟的标志——《简单之美》(前言) . 成功的软件项目就是那些提交产物达到或超出客户的预期的项目,而且开发过程符合时间和费...

    DataPipeline 评论0 收藏0
  • 聊一聊PHP依赖注入(DI) 和 控制反转(IoC)

    摘要:前言最近在使用框架,看了下他的源码,发现有很多地方也用到了依赖注入控制反转,觉得有必要和大家简单聊一聊什么是依赖注入以及怎么使用它。概念依赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。 前言 最近在使用ThinkPHP5框架,看了下他的源码,发现有很多地方也用到了依赖注入(控制反转),觉得有必要和大家简单聊一聊什么是依赖注入以及怎么使用它。 简介 I...

    sixgo 评论0 收藏0
  • 搞懂依赖注入, 用 PHP 手写简易 IOC 容器

    摘要:依赖注入控制反转的一种具体实现方法。接下来,我们使用依赖注入实现控制反转,使依赖关系倒置依赖被动传入。从单元测试的角度看,依赖注入更方便和操作,方便了测试人员写出质量更高的测试代码。 前言 好的设计会提高程序的可复用性和可维护性,也间接的提高了开发人员的生产力。今天,我们就来说一下在很多框架中都使用的依赖注入。 一些概念 要搞清楚什么是依赖注入如何依赖注入,首先我们要明确一些概念。 D...

    antz 评论0 收藏0
  • Spring还可以这么学--IoC(控制反转) / DI(依赖注入)理解

    摘要:对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形。控制被反转之后,获得依赖对象的过程由自身管理变为了由容器主动注入。于是,他给控制反转取了一个更合适的名字叫做依赖注入。 Spring还可以这么学--IoC(控制反转) / DI(依赖注入)理解 声明:文章的前三部分参考博文:https://www.cnblogs.com/Nouno...这篇文章首发是在我的个人微信订阅号每天学编...

    atinosun 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<