虽然我知道它的好用,但不要过度使用它。例如:
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与所有应用程序高度耦合。他们也不再能够投入其他应用程序。
答案 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容器帮助我们做的是将耦合集中到整个应用程序中的一个单点,而不是在整个应用程序周围进行耦合。