问题
程序中经常遇到这样的问题,A依赖于B,B依赖于C 因此需要解耦,而解耦的关键在于执行控制权与代码定义分离。
<?php
// 定义与执行
class Bim
{
public function doSomething()
{
echo __METHOD__, '|',"\n";
}
}
class Bar
{
private $bim;
public function __construct(Bim $bim)
{
$this->bim = $bim;
}
public function doSomething()
{
$this->bim->doSomething();
echo __METHOD__, '|',"\n";
}
}
class Foo
{
private $bar;
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
public function doSomething()
{
$this->bar->doSomething();
echo __METHOD__, '|',"\n";
}
}
class Ioc
{
public static $registry = [];
public static function bind($name, callable $resolver)
{
static::$registry[$name] = $resolver;
}
public static function make($name)
{
if (isset(static::$registry[$name])) {
$resolver = static::$registry[$name];
return $resolver();
}
throw new Exception('Alias does not in the IOC');
}
}
Ioc::bind('bar',function(){ //2 不会报错,此处只是代码绑定,而非执行make('bim')
return new Bar(Ioc::make('bim'));
// Ioc::make('bim');
});
// print_r(Ioc::$registry['bar']()); //3 执行会报错,此时虽然bar绑定了,但依赖的bim还没有在ioc中注册
// echo "\n";
Ioc::bind('bim',function(){ //1
return new Bim();
});
echo "-----2","\n";
print_r(Ioc::$registry);
echo "\n";
Ioc::bind('foo',function(){
return new Foo(Ioc::make('bar'));
});
$foo = Ioc::make('bar');
// $foo->doSomething();
echo '---',"\n";
class A{
public static $registry = [];
}
关键:绑定VS执行
使用函数闭包绑定,当闭包内一个执行片段,执行片段依赖于其它对象。如果该对象没有注册,绑定闭包并不会报错。因行执行的错误只有在运行时才能检查,而非定义时检查。使用函数的代码片段,实际是将执行权限外移了。函数内的依赖只要在函数执行前完成注入,使用函数便不成问题。