OOD,面向对象设计html
DIP,依赖倒置(软件设计原则)设计模式
IOC,控制反转(软件设计模式)ide
DI,依赖注入函数
IOC Container,控制反转容器,也是依赖注入容器测试
服务清单(功能清单,service list)this
服务(高层类,service ,对外提供服务)设计
服务提供者(底层类,service provider ,实际提供服务的对象)code
依赖倒置原则,它转换了依赖,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口htm
详细介绍请点我对象
提供一个计算机储存的服务。须要根据不一样的用户需求,使用不一样的存储设备。
// 定义一个 硬盘存储类 (服务提供者) class HardDiskStorage { public function saveToHardDisk(){ } public function readFromHardDisk(){ } } // 定义一个 U盘存储类(服务提供者) class UStorage { public function saveToU(){ } public function readFromU(){ } }
/** * 定义一个 ComputerStorage 类(存储服务) */ // 第一种:使用硬盘做为提供实际服务的对象 class ComputerStorage { protected $_storage = null; function __construct(){ $this->_storage = new HardDiskStorage(); } public function save(){ $this->_storage->saveToHardDisk(); } public function read(){ $this->_storage->readFromHardDisk(); } } // 第二种:使用 U 盘做为提供实际服务的对象 class ComputerStorage { protected $_storage = null; function __construct(){ $this->_storage = new UStorage(); } public function save(){ $this->_storage->saveToU(); } public function read(){ $this->_storage->readFromU(); } } // 读取 $cs = new ComputerStorage(); $cs->read();
根据上面的代码,当切换服务提供者时,服务类的代码须要作较多的改动。服务(ComputerStorage
)本省做为一个高层类,对外提供访问,却受制于提供具体服务的服务提供者(HardDiskStorage
、UStorage
)定义的实现(saveToHardDisk
、saveToU
、readFromHardDisk
、readFromU
),高层模块依赖底层模块实现,违背了依赖倒置原则。
同 2.1
介绍中场景。
interface ServiceList { public function save(); public function read(); }
// 硬盘 class HardDiskStorage implements ServiceList { public function save(){ } public function read(){ } } // U 盘 class UStorage implements ServiceList { public function save(){ } public function read(){ } }
class ComputerStorage { protected $_storage = null; function __construct(){ $this->_storage = new HardDiskStorage(); } public function save(){ $this->_storage->save(); } public function read(){ $this->_storage->read(); } } $cs = new ComputerStorage(); $cs->read();
上述代码中,事先定义了好了服务清单(接口,ServiceList
),而后服务提供者实现这些接口(HardDiskStorage
、UStorage
),服务(ComputerStorage
)只须要切换服务提供者便可(HardDiskStorage
、UStorage
),彻底无需理会他们的实现(readFromHardDisk
、readFromU
...等)。高层模块不依赖于底层模块定义的实现,遵循了依赖倒置原则
控制反转(IoC),它为相互依赖的组件提供抽象,将依赖(低层模块)对象的得到交给第三方(系统)来控制,即依赖对象不在被依赖模块的类中直接经过new来获取
同 2
场景
2
中的例子就是没有实现控制反转的例子。2
中 ComputerStorage
获取依赖(HardDiskStorage
或 UStorage
)的途径都是在 contruct
构造函数中获取的,即 类内部实例化依赖获取。
如下代码是根据 2
中的代码作了些许的调整。
class ComputerStorage { protected $_storage = null; /** * 内部只获取依赖的实例 */ public function setStorage($storage){ $this->_storage = $storage; } public function save(){ $this->_storage->save(); } public function read(){ $this->_storage->read(); } } // 外部实例化依赖 $hardDiskStorage = new HardDiskStorage(); $cs = new ComputerStorage(); // 注入依赖 $cs->setStorage($hardDiskStorage);
同 2
场景。
class Container { // 注册表 protected static $_registry = null; // 保存到注册表 public static function set($classname , Callable $create){ self::$_registry[$classname] = $create; } // 获取注册表对应类的实例 public static function get($key){ call_user_func(self::$_registry[$key]); } } class ComputerStorage { protected $_storage = null; function __construct(){ $this->_storage = Container::get('HardDiskStorage'); } public function read(){ $this->_storage->read(); } public function save(){ $this->_storage->save(); } } /** * 注册依赖 */ Container::set('HardDiskStorage' , function(){ return new HardDiskStorage(); }); Container::set('UStorage' , function(){ return new UStorage(); }); // 测试 $cs = new ComputerStorage(); $cs->read();