PHP控制反转(IOC)和依赖注入(DI)
一:构造注入:
<?php
class Main
{
public $name;
//构造注入
public function __construct($str)
{
$this->name = $str;
}
public function Method()
{
$this->name->Method();
}
}
class A
{
public function Method()
{
echo '我是A';
}
}
class B
{
public function Method()
{
echo '我是B';
}
}
$a=new Main(new A()); //注入A类
$a->Method();Main类依赖A类,通过构造器传入参数,一旦A类参数发生修改,Main类不需要改动,只需修改调用的地方,因为A类的创建在外部,这样Main类就无需关心A类。
二:工厂模式
<?php
interface Getdata
{
public function Method();
}
class A implements Getdata
{
public function Method()
{
echo "我是A";
}
}
class B implements Getdata
{
public function Method()
{
echo "我是B";
}
}
class Factory
{
public static function bind($transport)
{
switch ($transport) {
case 'A':
return new A();
break;
case 'B':
return new B();
break;
}
}
}
$getdata = Factory::bind('A'); // 加载A类
$getdata -> Method();
进一步解耦出来,这里AB类参数需要改动,只需要改动Factory类,Main可以设置切换不同的类,这种模式很常见,比如缓存,自由切换memcache,redis,db等,都可以用这种模式切换。这种需要一一对应,各类的实例化在工厂中完成,各类的方法结构必须统一,如果需求增加,工厂也会变的更庞大。
三:IOC容器
依赖注入:从应用程序的角度描述,可以把依赖注入,即:应用程序依赖容器创建并注入它所需要的外部资源;只要不是由内部生产(比如初始化、构造函数 __construct 中通过工厂方法、自行手动 new 的),而是由外部以参数或其他形式注入的,都属于依赖注入
控制反转:从容器的角度描述,即:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。
两者从不同角度解释,一句话和工厂模式的区别:高层模块不应该依赖于低层模块,二者都应该依赖于抽象,这样各层之间解耦。
1:simple di container的容器代码
<?php
class A
{
public function Method()
{
echo "我是A";
}
}
// simple di container的容器代码
// 该代码使用了后期静态绑定
class IoC
{
protected 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 exist in the IoC registry.'); //Ioc中没有别名
}
}
IoC::bind('a', function () {
return new A();
}); //这里只是先注册进去,不执行,传递 object(Closure)类型
$a = Ioc::make('a'); //从容器取得A
$a->Method(); //执行方法PHP后期绑定:http://php.net/manual/zh/language.oop5.late-static-bindings.php
2:Twittee容器代码,该代码使用了魔术方法
<?php
class A
{
public function Method()
{
echo "我是A";
}
}
//Twittee容器代码
class Container
{
private $s = array();
function __set($k, $c) //注册
{
$this->s[$k] = $c;
}
function __get($k) //获取
{
return $this->s[$k]($this);
}
}
$Ioc = new Container();
$Ioc->A = function () {
return new A();
};
$Ioc->A->Method();