学习笔记,使用xdebug跑了几遍代码,加深对IOC容器的理解。
解决了类之间依赖的问题,实现了代码之间的解耦
原文链接 https://xueyuanjun.com/post/769
<?php
//解读深入理解控制反转和依赖注入 原文链接 https://xueyuanjun.com/post/769
// DI 依赖注入 只要不是由内部生产(比如初始化、构造函数 __construct 中通过工厂方法、自行手动 new 的),而是由外部以参数或其他形式注入的
// IoC 控制反转 这种由外部负责其依赖需求的行为 (比如不在构造函数中写死,而通过传入参数,触发构造函数中的的代码处理依赖)
// 工厂模式,为了给超人制造超能力模组,我们创建了一个工厂,它可以制造各种各样的模组,且仅需要通过一个方法 case 处理
// IoC 容器 工厂模式的升华,容器中,放实例或者闭包函数
// 契约 接口的使用,换了一种表达而已
// class_alias() 给类创建别名的函数
interface SuperModuleInterface
{
/**
* 超能力激活方法
*
* 任何一个超能力都得有该方法,并拥有一个参数
*@param array $target 针对目标,可以是一个或多个,自己或他人
*/
public function activate(array $target);
}
class XPower implements SuperModuleInterface
{
public function activate(array $target)
{
// 这只是个例子。。具体自行脑补
echo '我具备X光能力';
}
}
class UltraBomb implements SuperModuleInterface
{
public function activate(array $target)
{
// 这只是个例子。。具体自行脑补
echo '我具备超级炸弹能力';
}
}
class Superman
{
public $module;
public function __construct(SuperModuleInterface $module)
{
$this->module = $module;
}
}
class Container
{
protected $binds;
protected $instances;
public function bind($abstract, $concrete)
{
if ($concrete instanceof Closure) {
$this->binds[$abstract] = $concrete;
} else {
$this->instances[$abstract] = $concrete;
}
}
public function make($abstract, $parameters = [])
{
//$parameters 亮点 制造超人的时候,传入一个数组(包含一个能力),后续call_user_func_array 就会传递两个参数
// 制造超能力的时候,$parameters 为空数组 后续call_user_func_array 就会传递$this参数
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
array_unshift($parameters, $this);
return call_user_func_array($this->binds[$abstract], $parameters);
}
}
// 创建一个容器(后面称作超级工厂)
$container = new Container;
// 向该 超级工厂添加超人的生产脚本
$container->bind('superman', function($container, $moduleName) {
return new Superman($container->make($moduleName));
});
// 向该 超级工厂添加超能力模组的生产脚本
$container->bind('xpower', function($container) {
return new XPower;
});
// 同上
$container->bind('ultrabomb', function($container) {
return new UltraBomb;
});
// ****************** 华丽丽的分割线 **********************
// 开始启动生产
/**
* 思路总结 container中绑定了各种闭包函数,只会在需要的时候调用
* 调用容器,制造一个具备某个能力的超人
* 过程 :1先调用超人的闭包函数, 执行 return new Superman($container->make($moduleName));
* 这一句触发制造超能力模组 例如 return new XPower; 生产超能力
* 2:超人的构造函数 $this->module = $module; 将制造的模组给与到超人
* 从而变量的值,是具备超能力模组的超人
**/
$superman_1 = $container->make('superman', ['xpower']);
$superman_2 = $container->make('superman', ['ultrabomb']);
$superman_3 = $container->make('superman', ['xpower']);
$superman_1->module->activate([]);
$superman_2->module->activate([]);