九 DIP 依赖倒置原则
首先看定义:
1.高层模块不依赖于低层模块,两者都应该依赖于抽象层
2.抽象不能依赖于细节,细节必须依赖于抽象
首先,模块是个抽象的概念,可以大到一个系统中的子系统作为一个模块,也可以是某个子系统中的组件,也可以是某个组件中的某个类。都可以称为模块。
先看第一条:
高层依赖于低层模块:是指高层模块需要调用低层模块的方法
再看第二条:
抽象不能依赖于细节:细节必须依赖于抽象,是指低层模块的方法实现应该是继承于接口,按照接口定义的抽象方法来实现,而不是接口去按照低层模块实现的方法来定义接口
最后:
两者都应该依赖于抽象层是指:高层的模块调用低层方法的依据是按照抽象层所开放出来的接口去调用,而不是抽象层下面具体的方法实现来调用。低层的模块应该去继承或者去实现抽象层的定义的抽象方法。
举例:
<?php /** * 驾驶员类 */ class Player { //这里定义了两个相同的方法名,不同参数的方法。这个在java中属于重载,但是PHP中的重载是指的动态的“创建”属性和方法,因此这里只是为了方便理解,PHP并不支持这种重载方式。 /** * 驾驶福特 * 不好的依赖,Player类的driver方法直接使用了Ford类中的run和stop方法 */ public function driver(Ford $car) { $car->run();//前进 $car->stop();//停止 } /** * 驾驶奔驰 * 不好的依赖,同上 */ public function driver(Benz $car) { $car->run(); $car->stop(); } } class Ford { public function run() { echo 'biu~~'; } public function stop() { echo 'duang'; } } class Benz { public function run() { echo 'biu~~'; } public function stop() { echo 'duang'; } }
从上面看,Player的两个驾驶方法都是直接使用了具体的类,如果某个类的方法发生了改变,例如类名发生了改变。那么Player类也要做相应的修改。
良好的依赖:
<?php /** * 驾驶员类 */ class Player { //fixme 这里定义了两个相同的方法名,不同参数的方法。这个在java中属于重载,但是PHP中的重载是指的动态的“创建”属性和方法,因此这里只是为了方便理解,PHP并不支持这种重载方式。 /** * 驾驶福特 * 依赖的是ICar接口,Player类不需要知道$car对象是Ford还是Benz,只要知道这两个品牌的车都实现了ICar接口即可 */ public function driver(ICar $car) { $car->run();//前进 $car->stop();//停止 } /** * 驾驶奔驰 * 不好的依赖,同上 */ public function driver(ICar $car) { $car->run(); $car->stop(); } }
interface Icar { public function run(); public function stop(); }
class Ford implements ICar { public function run() { echo 'biu~~'; } public function stop() { echo 'duang'; } } class Benz implements ICar { public function run() { echo 'biu~~'; } public function stop() { echo 'duang'; } }