Php 理解IoC容器和依赖注入
我的理解:Php 理解IoC容器和依赖注入,php,oop,inheritance,dependency-injection,inversion-of-control,Php,Oop,Inheritance,Dependency Injection,Inversion Of Control,我的理解: 依赖性是指ClassA实例需要ClassB实例来实例化新的ClassA实例的情况 依赖项注入是指通过ClassA构造函数中的参数或set~DependencyNameHere~(~DependencyNameHere~$param)函数将ClassA传递给ClassB的实例。(这是我不能完全确定的领域之一) IoC容器是一个单例类(在任何给定时间只能实例化一个实例),在这里可以注册为该项目实例化这些类对象的特定方式 因此,在这一点上,我开始尝试在更复杂的场景中使用IoC容器。到目
- 依赖性是指ClassA实例需要ClassB实例来实例化新的ClassA实例的情况
- 依赖项注入是指通过ClassA构造函数中的参数或set~DependencyNameHere~(~DependencyNameHere~$param)函数将ClassA传递给ClassB的实例。(这是我不能完全确定的领域之一)李>
- IoC容器是一个单例类(在任何给定时间只能实例化一个实例),在这里可以注册为该项目实例化这些类对象的特定方式李>
- 我试图在不违反OOP原则的情况下完成上述工作是否可行?我知道C++中可以使用动态内存和复制构造函数来完成它,但是我在PHP中还没有找到那种功能。(我承认,除了_构造之外,我几乎没有使用任何其他神奇方法的经验,但是从阅读和_克隆中,如果我理解正确,我无法在构造函数中使用它使正在实例化的子类成为父类实例的克隆)
- 与IoC相关的所有依赖类定义应该放在哪里?(我的IoC.php是否应该在顶部有一大堆require_once('dependencyClassDefinition.php')?我的直觉反应是有更好的方法,但我还没有想出一个)
- 我应该在哪个文件中注册我的对象?当前正在执行类定义之后对IoC.php文件中的IoC::register()的所有调用
- 在注册需要依赖关系的类之前,我是否需要在IoC中注册依赖关系?因为在我实际实例化IoC中注册的对象之前,我不会调用匿名函数,所以我猜不会,但这仍然是一个问题
- 还有什么我忽略了的,我应该做或使用的吗?我试图一步一个脚印地完成它,但我也不想知道我的代码是可重用的,最重要的是,对我的项目一无所知的人可以阅读和理解它
class Car {
public function start() {
$engine = new Engine();
$engine->vroom();
}
}
汽车
取决于发动机
<代码>发动机是汽车
的依赖项。但这段代码相当糟糕,因为:
- 依赖是隐性的;直到你检查
汽车的代码,你才知道它在那里
- 类是紧密耦合的;出于测试目的,您不能将
替换为发动机
,或在不修改模拟发动机
的情况下扩展原发动机的汽车
涡轮发动机
- 对于一辆汽车来说,为自己制造发动机看起来有点傻,不是吗
汽车
需要引擎
这一事实明确并明确地为其提供一个:
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);
上面是构造函数注入的一个示例,其中依赖项(依赖对象)通过类构造函数提供给依赖项(使用者)。另一种方法是在Car
类中公开setEngine
方法,并使用它注入Engine
的实例。这被称为setter注入,主要用于应该在运行时交换的依赖项
任何一个非平凡的项目都是由一堆相互依赖的组件组成的,它很容易忘记什么东西很快就被注入到哪里。依赖项注入容器是一个对象,它知道如何实例化和配置其他对象,知道它们与项目中其他对象的关系,并为您执行依赖项注入。这使您可以集中管理所有项目的(相互)依赖关系,更重要的是,可以更改/模拟其中的一个或多个,而无需编辑代码中的大量位置
让我们抛开汽车的类比,看看OP试图实现什么作为一个例子。假设我们有一个数据库
对象,具体取决于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
的一个实例来组装ins
$database = $dic->resolve('database');