学习记录-Laravel 核心 依赖注入 控制反转 反射

控制反转 依赖注入理解

interface DbConnect {

    public function connect();
}

class DbA implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo 'A';
    }
}
class DbB implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo "B";
    }
}

class ConnectDb {

    protected $connects;

    public function __construct()
    {
        $this->connect = new DbA();
    }

    public function connect()
    {
        echo $this->connect->connect();
    }
}

上面写法可以实现数据库连接功能,但是要切换到B数据库就要修改ConnectDb类,这样代码没法达到低耦合,也不符合编程开放封闭原则。我们可以把连接的类用函数传参的方式传进ConnectDb构造函数里.

class ConnectDb {

    protected $connects;

    public function __construct(DbConnect $dbConnect)
    {
        $this->connect = $dbConnect;
    }

    public function connect()
    {
        echo $this->connect->connect();
    }
}

$ConnectDb = new ConnectDb(new DbA());
$ConnectDb->connect();

这样我们就可以不修改ConnectDb而是用构造函数参数传递的方式切换数据库,这就是控制反转(感觉好像工厂模式。。。),不需要自己内容修改,通过外部传递参数,这种由外部负责其依赖需求的行为,称控制反转(IoC)

不通过自己内部new 对象或者实例,而是通过函数或者构造函数传递进来。称为依赖注入(DI)

反射

刚毕业那会面试一家公司面试就问我了不了解反射,当时给我问的一懵。工作这么长时间了其实还是不了解。。。。

反射其实就是根据类名返回这个类的任何信息,比如该类的方法,参数,属性等等

ReflectionClass 类报告了一个类的有关信息。

//   — 初始化 ReflectionClass 类
$reflectionClass = new ReflectionClass('ConnectDb');

//   — 获取类的构造函数   一个 ReflectionMethod 对象,反射了类的构造函数,或者当类不存在构造函数时返回 NULL。
$constructor     = $reflectionClass->getConstructor();

//   - 获取构造函数所有依赖参数
$dependencies    = $constructor->getParameters();

//   - 创建类的新的实例。给出的参数将会传递到类的构造函数。
$ConnectDb       = $reflectionClass->newInstance();

//   - 创建一个类的新实例,给出的参数将传递到类的构造函数。这个参数以 array 形式传递到类的构造函数 返回值 返回类的实例
$ConnectDb       = $reflectionClass->newInstanceArgs($dependencies);

我们可以创建一个方法,利用反射的机制拿到ConnectDb类的构造函数,然后拿到构造函数的参数对象,用递归的方法创建参数依赖,最后调用newInstanceArgs方法生成ConnectDb实例

interface DbConnect {

    public function connect();
}

class DbA implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo 'A';
    }
}
class DbB implements DbConnect {

    public function connect()
    {
        // TODO: Implement test_echo() method.
        echo "B";
    }
}

class ConnectDb {

    protected $connects;
    //反射是不能动态创建接口的
    public function __construct(DbA $dbConnect)
    {
        $this->connect = $dbConnect;
    }

    public function connect()
    {
        echo $this->connect->connect();
    }
}

function make ($concrete) {
    //   — 初始化 ReflectionClass 类
    $reflectionClass = new ReflectionClass($concrete);
    //   — 获取类的构造函数   一个 ReflectionMethod 对象,反射了类的构造函数,或者当类不存在构造函数时返回 NULL。
    $constructor     = $reflectionClass->getConstructor();

    //如果不需要传递参数直接返回实例
    if (is_null($constructor)) {
        return $reflectionClass->newInstance();
    } else {
    //   - 获取构造函数所有依赖参数
        $dependencies    = $constructor->getParameters();
        $instance = getdependencies($dependencies);
        return $reflectionClass->newInstanceArgs($instance);
    }

}

function getdependencies($parameter)
{
    $dependencies = [];
    foreach ($parameter as $paramete) {
        //返回对象实例 object 所属类的名字。返回对象实例 object 所属类的名字。 如果 object 不是一个对象则返回 FALSE。
        $dependencies[] = make($paramete->getClass()->name);
    }
    return $dependencies;
}

$ConnectDb = make('ConnectDb');
$ConnectDb->connect();

总结:

  • 控制反转(IoC):不修改类内部自身,通过外部参数传递的方式,由外部负责其依赖需求的行为。
  • 依赖注入(DI) :不通过自己new 或实例实例化,通过函数或者构造函数传递进来。
  • 反射:根据类名获取类的信息,方法、属性、参数等等

文章借鉴,也不算借鉴了。抄了深入laravel核心有兴趣的可以去看一下,也是自己做个记录。

本作品采用《CC 协议》,转载必须注明作者和本文链接
与其感慨路难行,不如马上出发
draven
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1
 public function __construct(DbA $dbConnect)
    {
        $this->connect = $dbConnect;
    }

这个没有注入interface,改成dbb还有改构造函数,应该有bind,将db绑定到a或者b

class Container
{
    protected $binds;

    protected $instances;

    public function bind($abstract, $concrete)
    {
        if ($concrete instanceof \Closure) {
            $this->binds[$abstract] = $concrete;
        } else {
            $this->instances[$abstract] = $concrete;
        }
    }

    public function make($abstract, $parameters = [])
    {
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }

        array_unshift($parameters, $this);

        return call_user_func_array($this->binds[$abstract], $parameters);
    }
}
   $container = new Container;

    $container->bind('db', function($container){
        return new DbA;
    });
    $container->bind('ConnectDb',function($container,$module){
        return new ConnectDb($container->make($module));
    });

    $computer = $container->make('ConnectDb',['db']);
    echo $computer->connect();//输出 A 
4年前 评论
draven (楼主) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!