依赖注入或实例化数据库类对象

时间:2015-04-16 01:07:53

标签: php dependency-injection

这似乎是一个广泛的问题,但是依赖注入与在__construct()调用中实例化类的实际用途是什么?

我基本上在需要它的类中实例化我的数据库对象:

class Example {
    private $db;

    function __construct() {
        $this->db = db::instance();
    }
}

我过去曾使用依赖注入,并且不知道是否可以简单地共享资源,例如从Model获取以下内容。

Class ExampleModel extends Model {

    function do_something() {
        $user = new User($db);
        $user->do_some_stuff();
    }
}

那么使用什么更有利?是否有任何与绩效相关的利弊?如果您需要对问题进行更多说明,请询问。


有很多积极的&关于依赖注入的负面看法:


对于任何感兴趣的人,这就是db::instance()的样子:

public static function instance() {
    if (!self::$instance) {
        $config = get_config();

        self::$instance = new self(
                $config['database']['host'], $config['database']['user'], $config['database']['pass'], $config['database']['db']
        );
    }
    return self::$instance;
}

1 个答案:

答案 0 :(得分:1)

总结我的评论 - 对我来说,如果你注入了依赖关系,那么Example不需要知道你注入的类是什么。如果您从Example中实例化该类,那么您需要确切地知道该类是什么。

这是一个问题/好处吗?取决于您,您的偏好和您的应用程序。我倾向于选择更抽象的方法。

例如,如果您执行了以下操作:

class Example {
    public function __construct(Injected $inj) {
        $this->db = $inj;
    }
}

...您可以看到您输入提示您期望$inj的内容。这可以是$inj直接所在的类的类型,也可以是$inj实现的接口类型 - 在这种情况下,您将知道$inj遵循您期望的一组指令

采用以下示例:

interface Db {
    public function fetch();
    public function insert();
}

class MyDb implements Db {
    public function fetch() {
        // ...
    }
    public function insert() {
        // ...
    }
}

如果您在Example课程中键入提示界面,则无需知道$injMyDb课程,但它实施Db - 重要的是要知道该类将遵循一组定义的规则(一个接口),例如这将实现fetch()insert()功能。没关系实际的课程 - 你只想要内容。

class Example {
    public function __construct(Db $inj) {
        var_dump(get_class($inj)); // string(4) "MyDb"
    }
}

这是注射及其益处的全部例子。直接实例化的等价物意味着您的Example需要了解MyDb

class Example {
    public function __construct() {
        $this->db = new MyDb; // implements Db, but you need to know exactly
                              // what the class is
    }
}

此方法消除了您将MyDb更改为YourDb的灵活性,而无需更改Example类。

再次,取决于你的情况。如果您的应用程序有可能在组件内进行更改或具有灵活性,则可能需要使用注入。如果它是合理的静态,那么你可以直接实例化。

我最后的评论是,当你对代码进行单元测试时,模拟注入的对象要比直接实例化的对象容易得多。