PHP - 如果自动加载,为什么要使用依赖注入?

时间:2016-04-26 19:24:05

标签: php dependency-injection autoload

请原谅这个问题的可能天真,但是我让自己真的很困惑。似乎最好使用依赖注入来解耦代码,以便您的类加载其依赖项。请想想以下类,其中Class Foo具有类Bar的依赖性

namespace Classes;

class Foo{

    protected barInstance;

    public function __construct(Bar $barInstance){
        $this->barInstance=$barInstance;
    }

}

但是,如果您正在自动加载您的课程,那么在不需要DI的情况下,以下内容完全相同吗?

namespace Classes;
use Classes/Bar;

class Foo{

    protected barInstance;

    public function __construct(){
        $this->barInstance=new Bar;
    }

}

感谢任何响应者。

4 个答案:

答案 0 :(得分:3)

自动加载确保您在引用它时定义了类。依赖注入使您可以灵活地使用您使用的对象的实例。

在您的示例中,假设您的Bar类管理数据库连接。并且假设您有时想要连接到不同的数据库。

public function __construct(){
    $this->barInstance = new Bar();
}

现在,您必须重构Foo课程以处理更改,因为您已将其与Bar的实例紧密耦合。

public function __construct(Bar $barInstance){
    $this->barInstance = $barInstance;
}

现在,在不更改Foo的情况下,我可以针对不同情况实例化Bar的不同实例。一个常用的例子是单元测试。

在这两种情况下,自动加载确保Bar及其所有依赖项都在Foo之外定义。

答案 1 :(得分:2)

以数据库连接为例。

你有

public class foo {
    public function __construct(DbConnectionInterface $db) { ... }
}

public class foo2 { 
    public function __construct(DbConnectionInterface $db) { ... }
}

...

等等

在你的“服务容器”中你有类似的东西

$db = new PdoDbConnection(); // which implements DbConnectionInterface

$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);

如果明天你想使用除了pdo之外的其他东西,那么你只需要建立一个实现该接口的新连接,然后就可以在一个地方更改你的数据库连接

$db = new NotPdoDbConnection(); // which implements DbConnectionInterface

$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);

如果您没有使用DI,那么您应该使用此类将所有类中的新PdoConnection()更改为新的NotPdoConnection()。但在这种情况下,自动加载对你来说无济于事。正如lsklyut所说,他回答了两个不同的概念。

它是一个“虚拟”案例,但你可以阅读一些有关DI的有趣文章

http://fabien.potencier.org/what-is-dependency-injection.html http://www.martinfowler.com/articles/injection.html

答案 2 :(得分:0)

这是两个独立的概念。自动加载将允许您不必在脚本中包含文件,并允许您按概念分隔您的类。就依赖注入而言,如果Bar有额外的依赖关系并且不能简单地通过使用新的Bar()来实例化,而是使用新的Bar($ dep1,$ dep2),那么创建Bar的逻辑将被隐藏在Foo的构造函数中,如以及需要Bar的任何其他类的构造函数。通过在注入之前反转创建Bar的依赖关系,你可以减轻Foo的额外责任。

答案 3 :(得分:0)

自动加载和依赖注入是无关的概念。

自动加载器知道如何加载类。当像new Foo()这样的简单语句运行时,解释器需要知道Foo类的定义。如果它还不知道它,那么它会调用自动加载器,直到该类可用。自动加载器知道每个类的定义位置并包含正确的文件。

依赖注入容器知道如何构建各种类型的对象。关于类加载它不知道(也不关心)。它假设当它运行new Bar()时,已经定义了类Bar(或者它可以被自动加载)。