七叶笔记 » golang编程 » PHP的依赖注入(DI)

PHP的依赖注入(DI)

依赖注入

概念 :是一种允许我们从硬编码的依赖中解耦出来,从而在运行时或者编译时能够修改的软件设计模式。

说明: 要想理解DI(依赖注入),首先要明白在PHP中是如何传递依赖关系的。

PHP中传递依赖关系的三种方式:

①在A类中直接new一个B类,代码如下:

 <?php
    //声明一个类B
    class B{
        //声明一个测试方法
        public function test(){
            //返回一个测试话术
            return '这是一个测试方法';
        }
    }
    //声明一个类A(假设A类想实现某个功能,要依赖B类来实现)
    class A{
        //声明一个测试方法
        public function toTest(){
            //声明一个B类的对象
            $bObj = new B();
            //调用B类的方法
            var_dump($bObj->test());
        }
    }
    //创建一个A类的对象
    $obj = new A();
    //调用A类的测试方法
    $obj->toTest();  

说明:这是一种最不可取的方案,这样的话A和B就耦合在一起了,也就是A类无法脱离B类而工作。

②在A类的方法中传入需要的B类,代码如下:

 <?php
//声明一个类B
class B{
    //声明一个测试方法
    public function test(){
        //返回一个测试话术
        return '这是一个测试方法';
    }
}
//声明一个类A(假设A类想实现某个功能,要依赖B类来实现)
class A{
    //声明一个变量
    public $b;
    //使用一个魔术方法
    public function __construct(B $b)
    {
        $this->b = $b;
    }
    //声明一个测试方法
    public function toTest(){
        //调用B类的方法
        var_dump($this->b->test());
    }
}
//创建一个A类的对象
$obj = new A(new B());
//调用A类的测试方法
$obj->toTest();  

说明:这种方式比第一种方式改进了不少,A类不必和B类捆绑在一起,只要传入的类满足A类的需求,也可以是C类,也可以是D类等等。但是这种方案的弊端在于如果A类依赖的类较多,参数列表会很长,容易发生混乱。

③使用set方法传入,代码如下:

 <?php
//声明一个类B
class B{
    //声明一个测试方法
    public function test(){
        //返回一个测试话术
        return '这是一个测试方法';
    }
}
//声明一个类A(假设A类想实现某个功能,要依赖B类来实现)
class A{
    //声明一个变量
    public $b;
    //声明一个测试方法
    public function set(B $b){
        //调用B类的方法
        $this->b = $b;
    }
    public function go(){
        var_dump($this->b->test());
    }
}
//创建一个A类的对象
$obj = new A();
//调用A类的测试方法(这个地方可以使用单例模式)
$obj->set(new B());
//调用go方法
$obj->go();  

说明:这种方法比第一种方法有了改进,A类不必与B类捆绑在一起,只要传入的类满足A类的需求,也可以是C类,也可以是D类等等。但是这种方案的弊端在于如果A类依赖的类较多,参数列表会很长,容易发生混乱,和第二种方案存在同样的弊端。当依赖的类增多时,我们会需要很多的set方法。

这个时候,我们如果有一个专门的类(或者说一个容器)可以帮我们管理这些依赖关系就好了–依赖注入

下面就是一个依赖注入的例子,代码如下:

 <?php
//声明一个容器类,用来注入对象
class Container
{
    //声明一个数组,用来存放对象
    private $s = array();
    //声明一个方法,用来实现对象的存放
    function set($k, $c)
    {
        //将对象存放进数组
        $this->s[$k] = $c;
    }
    //声明一个方法,用来获取对象
    function get($k)
    {
        //返回对应的对象
        return $this->s[$k];
    }
}
//声明一个Db类
class Db
{
    //声明一个方法
    public function doSomething(){
        //返回话术
        return '这是一个依赖注入的测试';
    }
}
//声明一个Cache类
class Cache
{
    //声明一个容器变量
    private $container;
    //使用构造函数给container赋值
    public function __construct(Container $container)
    {
        //将容器对象赋值给变量
        $this->container = $container;
    }
    //声明一个方法
    public function doSomething($str){
        //执行Db类中对应的方法
        var_dump($this->container->get($str)->doSomething());
    }
}
//创建一个Container对象
$container = new Container();
//在容器中注入两个类
$container->set('db', new Db());
$container->set('cache', new Cache($container));
//执行对应的方法
$container->get('cache')->doSomething('db');  

说明:这样是不是就好多了,不会出现上面三种情况的问题了呢?希望小伙伴们自己也尝试一下,体验一下,依赖注入设计模式的魅力吧!

下一篇文章我将给大家介绍一下什么是控制反转!希望大家不要错过!

相关文章