所谓开闭原则就是一个软件实体如类、模块和函数应该对扩展开放、对修改关闭。
强调用抽象构建框架,实现实现拓展细节。前端
有优势是提升软件的复用性和易维护展性。是面向对象的最基本原则。java
高层模块不该该依赖底层模块,两者都应该依赖其抽象。
抽象不该该依赖细节:细节应该依赖抽象。
针对接口编程,不要针对实现编程。编程
下降耦合提升稳定性,提升代码的可读性和易维护性。减小代码在修改时可能形成的风险。框架
下面咱们用代码来讲明啥是依赖倒置原则ide
假设咱们想实现一我的在学习的需求,咱们能够这样写函数
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class Redstar { public void studyJava() { System.out.println("redstar 在学习java"); } public void studyFE() { System.out.println("redstar 在学习前端"); } }
而后有个测试类学习
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class RedstarTest { public static void main(String[] args) { Redstar redstar = new Redstar(); redstar.studyFE(); redstar.studyJava(); } }
这时假设咱们还想要学习Python那么咱们则须要去修改Redstar这个类。这样写法是面向实现编程,由于整个Redstar类就是一个实现类。这个redstar类是要常常被修改的。也就拓展性比较差。咱们这个RedstarTest类就是应用层(高层模块)的类是依赖于这个Redstar实现类(底层模块)的。由于咱们没有抽象。根据依赖倒置原则高层次的模块不该该去依赖低层次的模块。每次Redstar拓展都要来RedstarTest进行补充。
咱们下面开始码具备依赖倒置的代码,首先建立一个接口。这个接口有个学习方法。测试
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public interface ICourse { void studyCourse(); }
下面写几个实现类,实现这个接口this
public class JavaCourse implements ICourse { @Override public void studyCourse() { System.out.println("redstar在学习Java课程"); } }
public class FECourse implements ICourse { @Override public void studyCourse() { System.out.println("redstar在学习FE课程"); } }
此时咱们将Redstar类修改成code
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class Redstar { public void studyJava(ICourse iCourse) { iCourse.studyCourse(); } }
Test类修改成
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class RedstarTest { public static void main(String[] args) { Redstar redstar = new Redstar(); redstar.studyJava(new JavaCourse()); redstar.studyJava(new FECourse()); } }
输出结果为
redstar在学习Java课程 redstar在学习FE课程
这时若是咱们还有其余大的课程想要学习咱们能够经过添加ICourse的实现类的方式来添加。
Redstar这个类是不会去动他的。对于想要学习什么课程咱们有RedstarTest类这高层类来本身选择。
顺便提一下咱们在RedstarTest类中使用接口方法的方式对ICourse接口的依赖进行注入。咱们也可使用构造器的方式对依赖进行注入。
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class Redstar { private ICourse iCourse; public Redstar(ICourse iCourse) { this.iCourse = iCourse; } public void studyJava() { iCourse.studyCourse(); } }
此时咱们Redstar中就应该这么写
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class RedstarTest { public static void main(String[] args) { JavaCourse javaCourse = new JavaCourse(); FECourse feCourse = new FECourse(); Redstar redstar = new Redstar(javaCourse); redstar.studyJava(); redstar = new Redstar(feCourse); redstar.studyJava(); } }
有构造器的方式一样咱们也能够用set 的方式,此时咱们的Redstar就要这么写了
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class Redstar { private ICourse iCourse; public void setiCourse(ICourse iCourse) { this.iCourse = iCourse; } public void studyJava() { iCourse.studyCourse(); } }
对应的RedstarTest就要这么写了
/** * @author 杨红星 * @version 1.0.0 * @date 2018/11/30 */ public class RedstarTest { public static void main(String[] args) { JavaCourse javaCourse = new JavaCourse(); FECourse feCourse = new FECourse(); Redstar redstar = new Redstar(); redstar.setiCourse(feCourse); redstar.studyJava(); redstar.setiCourse(javaCourse); redstar.studyJava(); } }
好到这里咱们的依赖倒置原则就讲完了,总结一下整体原则就是面向接口编程,或者说面向抽象编程。上面例子中的接口咱们也可使用抽象类来代替。同窗们可使用抽象类模拟一下上面的过程。