DIY 实现 ThinkPHP 核心框架(八)控制反转和依赖注入

软件工程提倡高内聚、低耦合,控制反转是一种有效的设计原则,而依赖注入是控制反转的一种实现方式。有以下代码

class Demo
{
    public function show()
    {
        $test = new Test();
    }
}

如果不实例化 Test 类, Demo 类也就没有意义。但是这种关系会增加代码的耦合性,如果 Test 类实例化方式改变, Demo 代码也要随之更改。如果类似的情况很多,项目代码会显得凌乱。
为解决这个问题, ThinkPHP 提供了一个容器类 Container , 创建 Test 实例的任务交由 Container类 完成,将 Test 实例作为参数传给 Demo 类的 show() 方法。
将创建实例的控制权交给 Container 类实现控制反转,而 show() 方法依赖的 Test 类通过参数从外部传入实现依赖注入。

class Demo
{
    public function show(Test $test)
    {}
}

创建 core/src/think/Container.php 文件

namespace think;

//use ReflectionClass;
//use ReflectionFunctionAbstract;
/**
 * 以下属性、方法的代码 ThinkPHP 5 与 6 中基本保持一致
 * 采用“拿来主义”
 * Class Container
 * @package think
 */
class Container
{
    protected  $instances = [];

    public function make (string $class)
    {
        $class = '\\think\\' . $class;
        if (!isset($this->instances[$class])) {
            $this->instances[$class] = new $class();
        }
        return $this->instances[$class];
    }

    public function show()
    {
        $request = $this->make('Request');
        $index = new \app\index\controller\Index();
        $index->show($request);
    }
}

创建 core/src/think/Request.php 文件

namespace think;

class Request
{}

修改 application/index/controller/Index.php , 引入 Request 类的命名空间,编写 show() 方法接受 Request 类的实例参数 $req 。

namespace app\index\controller;

use think\Request;

class Index
{
    public function show (Request $req)
    {
        var_dump($req instanceof Request);
    }
}

修改入口文件 public/index.php 进行测试

require __DIR__ . '/../core/base.php';

(new \think\Container)->show();

访问 diy.tp ,运行结果为 bool(true) 说明成功实现依赖注入。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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