加入收藏 | 设为首页 | 会员中心 | 我要投稿 西双版纳站长网 (https://www.0691zz.com.cn/)- 数据计算、IT业界、服务器、教程、云日志!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

教你如何手动创建PHP DI容器

发布时间:2022-08-11 12:03:19 所属栏目:PHP教程 来源:互联网
导读:关于依赖注入相信大家应该都经常接触或者至少有所耳闻,比较知名的框架都支持依赖注入,比如Java的Spring,PHP的Laravel、Symfony等。现在我开始手动实现一个简陋的DI容器吧。 由开车开始 先开个车,为大家举个栗子: class Driver{ public function drive()
关于依赖注入相信大家应该都经常接触或者至少有所耳闻,比较知名的框架都支持依赖注入,比如Java的Spring,PHP的Laravel、Symfony等。现在我开始手动实现一个简陋的DI容器吧。
 
由开车开始
先开个车,为大家举个栗子:
 
 
 
 
 
 
 
 
 
class Driver{    public function drive()
 
    {
 
        $car = new Car();        echo '老司机正在驾驶', $car->getCar(), PHP_EOL;
 
    }
 
}class Car{    protected $name = '普通汽车';    public function getCar()
 
    {        return $this->name;
 
    }
 
}
 
有两个类,Driver和Car,老司机Driver有个方法driver,在调用的时候首先得整辆车$car,然后发车。大多数同学都写过这样或者类似的代码,这样的代码单看没啥毛病,挺正常的。但是,如果我要换辆车,开普通车撩不到妹。
 
 
 
class Benz extends Car{    protected $name = '奔驰';
 
}
 
这时候就需要做一个比较恶心的操作了,得改老司机的代码了。(老司机:我做错了什么?换辆车还得让我重学驾照……)。因此我们需要把让Car为外界注入,将Driver和Car解耦,不是老司机自己开车的时候还得自己去造车。于是就有了下面的结果
 
 
 
 
 
 
 
class Driver{    protected $car;    public function __construct(Car $car)
 
    {        $this->car = $car;
 
    }    public function drive()
 
    {        echo '老司机正在驾驶', $this->car->getCar(), PHP_EOL;
 
    }
 
}
 
此时Driver和Car两个类已经解耦,这两个类的依赖,依靠上层代码去管理。此时,老司机会这样“开车”:
 
 
 
 
$car = new Car();
 
$driver = new Driver($car);
 
$driver->drive();
 
此时,我们创建Driver依赖的实例,并注入。上面的例子,我们实现了依赖注入,不过是手动的,写起来感觉还是不爽。这么繁重的活怎么能手动来做呢,得让程序自己去做。于是乎,DI容器诞生。
 
依赖注入容器
依赖注入与IoC模式类似工厂模式,是一种解决调用者和被调用者依赖耦合关系的模式。它解决了对象之间的依赖关系,使得对象只依赖IoC/DI容器,不再直接相互依赖,实现松耦合,然后在对象创建时,由IoC/DI容器将其依赖(Dependency)的对象注入(Inject)其内,这样做可以最大程度实现松耦合。依赖注入说白一点,就是容器将某个类依赖的其他类的实例注入到这个类的实例中。
 
这段话可能说的有点抽象,回到刚才的例子吧。刚刚我手动完成了依赖注入,比较麻烦,如果一个大型的项目这样做肯定会觉得很繁琐,而且不够优雅。因此我们需要有一位总管代替我们去干这个,这个总管就是容器。类的依赖管理全部交给容器去完成。因此,一般来说容器是一个全局的对象,大家共有的。
 
做一个自己的DI容器
写一个功能,我们首先需要分析问题,因此我们先要明白,对于一个简单的DI容器需要哪些功能,这直接关系到我们代码的编写。对于一个简单的容器,至少需要满足以下几点:
 
创建所需类的实例
 
完成依赖管理(DI)
 
可以获取单例的实例
 
全局唯一
 
综上,我们的容器类大约长这样:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class Container{    /**
 
     * 单例
 
     * @var Container
 
     */
 
    protected static $instance;    /**
 
     * 容器所管理的实例
 
     * @var array
 
     */
 
    protected $instances = [];    private function __construct(){}  
 
    private function __clone(){}    /**
 
     * 获取单例的实例
 
     * @param string $class
 
     * @param array ...$params
 
     * @return object
 
     */
 
    public function singleton($class, ...$params)
 
    {}    /**
 
     * 获取实例(每次都会创建一个新的)
 
     * @param string $class
 
     * @param array ...$params
 
     * @return object
 
     */
 
    public function get($class, ...$params)
 
    {}    /**
 
     * 工厂方法,创建实例,并完成依赖注入
 
     * @param string $class
 
     * @param array $params
 
     * @return object
 
     */
 
    protected function make($class, $params = [])
 
    {}    /**
 
     * @return Container
 
     */
 
    public static function getInstance()
 
    {        if (null === static::$instance) {            static::$instance = new static();
 
        }        return static::$instance;
 
    }
 
}

(编辑:西双版纳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读