依赖倒置原则(Dependence Inversion Principle,DIP)
High level modules should not depend upon low level modules.Both should depend upon
abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.
翻译过来,包含三层含义:
● 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
● 抽象不应该依赖细节;
● 细节应该依赖抽象。
容高层模块和低层模块容易理解,每一个逻辑的实现都是由原子逻辑组成的,不可分割的
原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。那什么是抽象?什么又是细节
呢?在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实
现类,实现接口或继承抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是
可以加上一个关键字new产生一个对象。依赖倒置原则在Java语言中的表现就是:
● 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过
接口或抽象类产生的;
● 接口或抽象类不依赖于实现类;
● 实现类依赖接口或抽象类。
更加精简的定义就是“面向接口编程”——OOD(Object-Oriented Design,面向对象设
计)的精髓之一。
“减少并行开发引起的风险”,什么是并行开发的风险?并行开发最大的
风险就是风险扩散,本来只是一段程序的错误或异常,逐步波及一个功能,一个模块,甚至
到最后毁坏了整个项目。为什么并行开发就有这样的风险呢?一个团队,20个开发人员,各
人负责不同的功能模块,甲负责汽车类的建造,乙负责司机类的建造,在甲没有完成的情况
下,乙是不能完全地编写代码的,缺少汽车类,编译器根本就不会让你通过!在缺少Benz类
的情况下,Driver类能编译吗?更不要说是单元测试了!在这种不使用依赖倒置原则的环境
中,所有的开发工作都是“单线程”的,甲做完,乙再做,然后是丙继续……这在20世纪90年
代“个人英雄主义”编程模式中还是比较适用的,一个人完成所有的代码工作。但在现在的大
中型项目中已经是完全不能胜任了,一个项目是一个团队协作的结果,一个“英雄”再牛也不
可能了解所有的业务和所有的技术,要协作就要并行开发,要并行开发就要解决模块之间的
项目依赖关系,那然后呢?依赖倒置原则就隆重出场了!
package DependenceInversionP; public interface IDriver { public void drive(ICar car); }
package DependenceInversionP; public class Driver implements IDriver{ @Override public void drive(ICar car) { car.run(); } }
package DependenceInversionP; public interface ICar { public void run(); }
package DependenceInversionP; public class BWM implements ICar{ public void run(){ System.out.println("BWM running"); } }
package DependenceInversionP; public class Benz implements ICar{ public void run(){ System.out.println("Benz is running"); } }
package DependenceInversionP; public class Client { public static void main(String[] args){ IDriver zhangsan = new Driver(); ICar benz =new Benz(); zhangsan.drive(benz); IDriver lisi = new Driver(); ICar bwm =new BWM(); zhangsan.drive(bwm); } }