首页 > di 依赖注入实现的意义是什么?

di 依赖注入实现的意义是什么?

一般的 PHP 框架,一个应用 Application,生命周期大概是这样的:Request > Router / Url > Dispatch > Controller/Action [ > Service] > Model > [ > View] > Response,当然可能有些差别,多数无外乎这样。

那引入 di 注入的意义是什么呢?是为了把应用流程涉及的对象设计成组件来实现解耦?比如 RequestInterface / HttpRequest / CliRequest,RouterInterface / SimpleRouter / RegexRouter / MapRouter 等?

但是一个普通的带视图带数据库操作的请求大致流程大家都一样啊(ROR / J2EE / PHP MVC),即使是 restful 也是有 Router / Request / ControllerAction / Response 的,这解耦的意义是什么呢?解来解去,还得捞出来组个 MVC 流程。就好像 Router 妥妥的依赖 Request,那就手工注入喽?Router 构造函数参数是 RequestInterface $request 喽?当前应用入口决定注入何种 Request 对象喽?难不成哪天 Router 还依赖个奇怪的玩意不成?

难道说仅仅是为了 mock 方便?还是说为了不确定的将来?还是说有其它的原因。。。


没错,就是解耦。
用个MVC就是解耦完成了?
这是最低层次的解耦好吗?


解耦、方便unit test,显式注入的比较方便管理、最蛋疼的是隐式注入、半天找不到源文件。 laravel的DI其实也就是Requests和services了。


就是为了解耦啊,简单的MVC就按照你上面的流程根本无法完成解耦。模块之间的依赖依然非常严重。


依赖注入是面向对象编程里面用来解耦的设计模式.

<?php
class db {
    public static function get_db() {
        return new mysqli('127.0.0.1','user','pass','dbname',3306);
    }
}
class post {
    private $db;
    public function set_db($db){
        $this->db = $db;
    }
    public function get_post($id){
        return $this->db->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
    }
}
$post = new post();
$post->set_db( db::get_db() ); //注入post类依赖的数据库连接对象,通过类名直接调用静态方法get_db
$post->get_post(1024);

对比下过程式的写法:

<?php
function db() {
    static $db; //静态变量避免重复连接
    if ($db) {
        return $db;
    } else {
        $db = new mysqli('127.0.0.1','user','pass','dbname',3306);
        return $db;
    }
}

function get_post_v1($db, $id) {
    return $db->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
}
get_post_v1(db(), 1024); //调用函数时注入依赖

function get_post_v2($id) {
    $db = db(); //在函数内部包含依赖(耦合?不见得)
    return $db->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
}
get_post_v2(1024);

$app['db'] = db(); //应用全局数组,Windows系统里的注册表?你的应用比Windows还复杂?
function get_post_v3($id) {
    global $app; //全局变量
    return $app['db']->query('SELECT * FROM post WHERE id ='.intval($id))->fetch_all();
}
get_post_v3(1024);

DI的前提是你需要一个统一的容器去承载你的bean,拥有这么一个容器的时候,你可以对里面的bean进行一些特殊的操作而且不用大篇幅的修改代码,难道这还不够吗?


我对DI的观点一向是,与其说依赖注入,不如说是依赖管理,其实有些类似于composer、pip、maven这种更高一层管理应用与库之间的依赖工具,DI框架会带来这些好处(前提是好的DI框架):

  1. 通过配置改变依赖接口的实现,这也是DI功能最基本和最核心的功能

  2. 灵活控制依赖实现的实例范围,单例、每个线程一个、每个请求一个等等

  3. 依赖的参数,依赖的依赖等管理

  4. 代码更加简洁、逻辑更加清楚

  5. Mock方便测试方便,这个有了1就好办

总的来说就是把应用中的功能块与功能块之间,类与类之间的依赖关系通过一个统一的框架集中管理起来。

【热门文章】
【热门文章】