简而言之(因为这不仅仅是 OOP 世界中的问题),依赖性是组件 A 需要(依赖)组件 B 来做它应该做的事情的情况。该词还用于描述此场景中的依赖组件。用 OOP/PHP 术语来说,请考虑以下与强制性汽车类比的示例:
class Car {
public function start() {
$engine = new Engine();
$engine->vroom();
}
}
Car
depends on Engine
. Engine
is Car
's 依赖性。这段代码非常糟糕,因为:
- 依赖性是隐式的;你不知道它在那里,直到你检查
Car
's code
- 类是紧密耦合的;你不能替代
Engine
with MockEngine
用于测试目的或TurboEngine
扩展原来的而不修改Car
.
- 汽车能够自己制造发动机看起来有点傻,不是吗?
依赖注入是解决所有这些问题的一种方法,通过以下事实Car
needs Engine
明确地并明确地为其提供一个:
class Car {
protected $engine;
public function __construct(Engine $engine) {
$this->engine = $engine;
}
public function start() {
$this->engine->vroom();
}
}
$engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine
$car = new Car($engine);
上面是一个例子构造函数注入,其中依赖项(被依赖对象)通过类构造函数提供给依赖项(消费者)。另一种方法是暴露setEngine
方法中的Car
类并使用它来注入一个实例Engine
。这被称为设定注射并且对于应该在运行时交换的依赖关系最有用。
任何重要的项目都由一堆相互依赖的组件组成,并且很容易很快就失去对注入内容的跟踪。 A依赖注入容器是一个知道如何实例化和配置其他对象、知道它们与项目中其他对象的关系并为您执行依赖项注入的对象。这使您可以集中管理项目的所有(相互)依赖项,更重要的是,可以更改/模拟其中一个或多个依赖项,而无需编辑代码中的一堆位置。
让我们放弃汽车类比,以 OP 试图实现的目标为例。假设我们有一个Database
对象取决于mysqli
目的。假设我们想使用一个非常原始的依赖关系检测容器类DIC
公开了两种方法:register($name, $callback)
注册一种以给定名称创建对象的方法,并且resolve($name)
从该名称获取对象。我们的容器设置看起来像这样:
$dic = new DIC();
$dic->register('mysqli', function() {
return new mysqli('somehost','username','password');
});
$dic->register('database', function() use($dic) {
return new Database($dic->resolve('mysqli'));
});
请注意,我们告诉容器获取一个实例mysqli
从自身组装一个实例Database
。然后得到一个Database
实例及其依赖项自动注入,我们只需:
$database = $dic->resolve('database');
这就是它的要点。一个稍微复杂但仍然相对简单且易于掌握的 PHP DI/IoC 容器是Pimple http://pimple.sensiolabs.org/。查看其文档以获取更多示例。
关于OP的代码和问题:
- 不要为您的容器(或任何其他与此相关的东西)使用静态类或单例;他们都是邪恶的 http://www.youtube.com/watch?v=-FRm3VPhseI。看看粉刺吧。
- 决定你是否想要你的
mysqliWrapper
class extend mysql
or depend on it.
- 通过致电
IoC
从内部mysqliWrapper
您正在将一种依赖关系替换为另一种依赖关系。您的对象不应该知道或使用容器;否则它就不再是 DIC,而是服务定位器(反)模式。
- 你不需要
require
在将其注册到容器中之前先创建一个类文件,因为您根本不知道是否要使用该类的对象。在一处完成所有容器设置。如果您不使用自动加载器,您可以require
在您向容器注册的匿名函数内。
其他资源:
-
控制容器反转和依赖注入模式 http://www.martinfowler.com/articles/injection.html马丁·福勒
-
不要寻找东西 http://www.youtube.com/watch?v=RlfLCWKxHJ0-- 关于 IoC/DI 的干净代码讨论