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();