兴奋地把什么投入依赖注入conatiner?不是DI会增加耦合吗?

时间:2016-09-04 14:01:08

标签: php dependency-injection

虽然我知道它的好用,但不要过度使用它。例如:

class Point
{
    private $x, $y, $graphicsEngine;

    public function __constructor($x, $y, $graphicsEngine)
    {
        $this->x = $x;
        $this->y = $y;
        $this->graphicsEngine = $graphicsEngine;
    }

    public function draw()
    {
        $this->graphicsEngine->draw($this);
    }
}

class GraphicsEngine
{
    public function draw(Point $p)
    {
        ....
    }
}

$graphicsEngine = new GraphicsEngine();
$graphicsEngine->draw (new Point(5,2));

点必须知道GraphicsEngine。如果我重写DI形式:

class Point
{
    private $x, $y;

    public function __constructor($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    public function draw()
    {
        DI::get('graphicsEngine')->draw($this);
    }
}

class GraphicsEngine
{
    public function draw(Point $p)
    {
        ....
    }
}

DI::set('graphicsEngine', new GraphicsEngine());
DI::get('graphicsEngine'->draw (new Point(5,2));
虽然DI本身与应用程序高度耦合,但这看起来有点轻松。 GraphicsEngine和Point曾经更加独立,但现在DI与所有应用程序高度耦合。他们也不再能够投入其他应用程序。

1 个答案:

答案 0 :(得分:1)

您的问题是您的对象不应该知道IoC容器的存在:

class Point
{
    private $x, $y;

    public function __constructor($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    public function draw()
    {
        DI::get('graphicsEngine')->draw($this); // WRONG: DIRECT REFERENCE TO DI!!!
    }
}

我试图提供帮助,因为我是JavaScript的IoC容器的作者。不幸的是,我并不熟悉您的IoC容器或PHP。我会尽力解释如何解决这个问题。

class Point
{
    private private $x, $y, $graphicsEngine;

    public function __constructor($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    public function draw()
    {
        // graphicsEngine is only used when draw is invoked
        // we can lazy inject graphicsEngine 
        $this->graphicsEngine->draw($this);
    }
}

class GraphicsEngine
{
    public function draw(Point $p)
    {
        ....
    }
}

要了解如何配置延迟注入,您需要参考lazy-injection

请记住您的对象不应该知道IoC容器的存在。您的IoC容器将在您的应用程序中的某处配置,所有IoC配置应集中在一个文件中。这个文件将充满类型绑定:

 DI::set('X', X);
 DI::set('Y', Y);
 // ...

类型绑定是密钥(例如graphicsEngine)和实现(例如GraphicsEngine)之间的映射。您可以将IoC容器配置视为类型绑定的字典。

IoC容器拥有类型绑定的字典。这意味着IoC容器知道应用程序中的所有类型(类和接口),但您的类型不知道IoC容器。

IoC容器就像一个" God"看到一切,你的对象都不知道这个"上帝"或其他类。您的类不会耦合,但需要在某处进行耦合,而某些地方则是IoC配置。

我们可以说IoC容器不会移除耦合,因为在运行时需要耦合。 IoC容器帮助我们做的是将耦合集中到整个应用程序中的一个单点,而不是在整个应用程序周围进行耦合。