https://my.oschina.net/u/3529405/blog/1821744
<?php /** * 依赖注入 IOC DI * 参考文章 * https://segmentfault.com/a/1190000002411255 * https://segmentfault.com/a/1190000002424023 */ /** * IOC * 控制反转 Inversion of Control * 依赖关系的转移 * 依赖抽象而非实践 * 比较实用的注入方式有三种 * Setter injection 使用setter方法 * Constructor injection 使用构造函数 * Property Injection 直接设置属性 */ // IOC 栗子 // 假设一个储存业务 // 定义接口 业务需求一个数据储存 到rides 或者 mysql 中 interface SaveIO { public function set (); } // 定义两种储存方式 并继承(implements)SaveIO 接口 // rides class RidesClass implements SaveIO { public function set () { echo 'rides_save'.PHP_EOL; } } // mysql class MysqlClass implements SaveIO { public function set (){ echo 'mysql_save'.PHP_EOL; } } // 高层业务 class Business { private $myBusiness; public function __construct ($ioc) { $this->myBusiness = $ioc; } public function save () { $this->myBusiness->set(); } // 替换依赖 public function replaceIOC ($ioc) { $this->myBusiness = $ioc; } } echo 'IOC------'.PHP_EOL; $bus = new Business(new RidesClass()); $bus->save(); // 输出rides_save // 替换成其他依赖 $bus->replaceIOC(new MysqlClass()); $bus->save(); // 输出 mysql_save /** * DI * 依赖注入 Dependency Injection * 容器自动根据配置,将依赖注入指定对象 * 管理应用程序中的『全局』对象(包括实例化、处理依赖关系)。 * 可以延时加载对象(仅用到时才创建对象)。 * 促进编写可重用、可测试和松耦合的代码。 */ // 首先需要一个容器 class ConComponent { protected $_di = array(); // 注册 依赖 让依赖存储在$_di 存储形式 $_di->['服务名称']->Closure public function register ($name,$service) { $this->_di[$name] = $service; } /** * public function save ($name) * 高层业务,可以另外拓展一个类,不要放在容器里 * (这里只是一个简易的写法,但是不要这样写) * 实现 class{ * $构造函数=容器返回依赖 * 高层业务根据需求 * 通过$_di[className]()创建依赖类 * 通过$_di[className]()->实现业务 * } * @param $name */ public function save ($name) { $this->_di[$name]()->set(); } } /* * 重复利用 RedisClass MysqlClass * 注册依赖 * */ $component = new ConComponent(); // 创建容器 /* * 注册依赖 * @param name 依赖的名称 * @param function(){} 是一个闭包(closure) * 所以只有在我们调用一次 $component->_di[name] * 才会创建一个依赖对象 实现需时创建 * */ $component->register('RedisClass',function () { return new RidesClass(); }); $component->register('MysqlClass',function () { return new MysqlClass(); }); echo 'di----'.PHP_EOL; $component->save('RedisClass'); // 输出rides_save $component->save('MysqlClass'); // 输出Mysql_save /** * AOP * Aspect-oriented programming * 面向方面编程 * 无需修改任何一行程序代码, * 将功能加入至原先的应用程序中, * 也可以在不修改任何程序的情况下移除 */