IoC 容器
原始版
- 每次创造不同能力的超人,都需要修改Superman类
class Superman
{
protected $power;
public function __construct()
{
$this->power = new Fight(9, 100);
// $this->power = new Force(45);
// $this->power = new Shot(99, 50, 2);
/*
$this->power = array(
new Force(45),
new Shot(99, 50, 2)
);
*/
}
}
class Flight
{
protected $speed;
protected $holdtime;
public function __construct($speed, $holdtime) {}
}
class Force
{
protected $force;
public function __construct($force) {}
}
class Shot
{
protected $atk;
protected $range;
protected $limit;
public function __construct($atk, $range, $limit) {}
}
//每次创造不同能力的超人,都需要修改Superman类
$superman = new Superman();
工厂
- 创建超人,初始化时,就根据不同的需求,传入不同的参数,最后得到不同能力的超人,能力可以是多个,能力值任意改变
- 不再依赖Superman类,但是依赖SuperModuleFactory工厂类,工厂类功能不够时,需要修改工厂类
class Factory
{
public function activate($moduleName, $options)
{
switch ($moduleName) {
case 'Fight': return new Fight($options[0], $options[1]);
case 'Force': return new Force($options[0]);
case 'Shot': return new Shot($options[0], $options[1], $options[2]);
}
}
}
class Superman
{
protected $power;
public function __construct(array $modules)
{
// 初始化工厂
$factory = new Factory;
// 通过工厂提供的方法制造需要的模块
foreach ($modules as $moduleName => $moduleOptions) {
$this->power[] = $factory->activate($moduleName, $moduleOptions);
}
}
}
class Flight
{
protected $speed;
protected $holdtime;
public function __construct($speed, $holdtime) {}
}
class Force
{
protected $force;
public function __construct($force) {}
}
class Shot
{
protected $atk;
protected $range;
protected $limit;
public function __construct($atk, $range, $limit) {}
}
// 创建超人,初始化时,就根据不同的需求,传入不同的参数,最后得到不同能力的超人,能力可以是多个,能力值任意改变
// 不再依赖Superman类,但是依赖SuperModuleFactory工厂类,工厂类功能不够时,需要修改工厂类
$superman = new Superman([
'Fight' => [9, 100],
'Shot' => [99, 50, 2]
]);
依赖注入
- 只要遵循超能力工厂SuperFactoryInterface接口的规范,谁都可以创造不同的超能力工厂,超人创建不再依赖工厂
- 但是每个超人都需要手动创建,效率低
class Superman
{
protected $power;
public function __construct(SuperFactoryInterface $module)
{
$this->power[] = $module->activate();
}
}
//工厂接口
interface SuperFactoryInterface
{
//返回超能力对象,如Fight,Shot
public function activate();
}
//X-超能量工厂
class XPowerFactory implements SuperFactoryInterface
{
public function activate()
{
return [new XPower([])];
}
}
//终极炸弹工厂
class UltraBombFactory implements SuperFactoryInterface
{
public function activate()
{
return [new UltraBomb([])];
}
}
class XPower
{
protected $x1;
protected $x2;
public function __construct($array) {}
}
class UltraBomb
{
protected $u;
protected $ul;
public function __construct($array) {}
}
//只要遵循超能力工厂SuperFactoryInterface接口的规范,谁都可以创造不同的超能力工厂,超人创建不再依赖工厂
//但是每个超人都需要手动创建
//X-超能量超人
$XPower = new XPowerFactory();
$superman1 = new Superman($XPower);
//终极炸弹超人
$UltraBomb = new UltraBombFactory();
$superman2 = new Superman($UltraBomb);
Ioc容器
- 向容器中添加创建超人的闭包 ,只有在真正的生产(make) 操作被调用执行时,才会触发。
- 当有新的需求,只需另外绑定一个“生产闭包”即可。
- 1条指令,就可以创建1个超人
class Superman
{
protected $power;
public function __construct(SuperFactoryInterface $module)
{
$this->power[] = $module->activate();
}
}
//工厂接口
interface SuperFactoryInterface
{
//返回超能力对象,如Fight,Shot
public function activate();
}
//X-超能量工厂
class XPowerFactory implements SuperFactoryInterface
{
public function activate()
{
return [new XPower([])];
}
}
//终极炸弹工厂
class UltraBombFactory implements SuperFactoryInterface
{
public function activate()
{
return [new UltraBomb([])];
}
}
class XPower
{
protected $x1;
protected $x2;
public function __construct($array) {}
}
class UltraBomb
{
protected $u;
protected $ul;
public function __construct($array) {}
}
class Container
{
protected $binds;//这里存创建超人的闭包,格式,"XPower"=>"创建XPower超人的闭包", "UltraBomb"=>"创建UltraBomb超人的闭包"
//$abstract,超人的名称
//$concrete,创建超人的闭包
public function bind($abstract, $concrete)
{
//必须是闭包才存下来
if ($concrete instanceof Closure) {
$this->binds[$abstract] = $concrete;
}
}
public function make($abstract, $parameters = [])
{
//存在这个闭包,就去执行
if (isset($this->binds[$abstract])) {
return call_user_func_array($this->binds[$abstract], $parameters);
}
}
}
// 向该超级工厂添加 xpower 超能力模组的生产脚本
$container->bind('xpower', function($container) {
//X-超能量超人
$XPower = new XPowerFactory();
$superman = new Superman($XPower);
return $superman;
});
// 向该超级工厂添加 终极炸弹 超能力模组的生产脚本
$container->bind('UltraBomb', function($container) {
//终极炸弹超人
$UltraBomb = new UltraBombFactory();
$superman = new Superman($UltraBomb);
return $superman;
});
//向容器中添加创建超人的闭包 ,只有在真正的生产(make) 操作被调用执行时,才会触发。
//当有新的需求,只需另外绑定一个“生产闭包”即可。
//1条指令,就可以创建1个超人
//正的 IoC 容器会根据类的依赖需求,自动在注册、绑定的一堆实例中搜寻符合的依赖需求,并自动注入到构造函数参数中去。Laravel 框架的服务容器正是这么做的
//这种自动搜寻依赖需求的功能,是通过 反射(Reflection) 实现的
//X-超能量超人
$xpower_1 = $container->make('xpower', []);
$xpower_2 = $container->make('xpower', []);
//终极炸弹超人
$UltraBomb_1 = $container->make('UltraBomb', []);
$UltraBomb_2 = $container->make('UltraBomb', []);
本作品采用《CC 协议》,转载必须注明作者和本文链接