所謂開閉原則就是一個軟件實體如類、模塊和函數應該對擴展開放、對修改關閉。
強調用抽象構建框架,實現實現拓展細節。前端
有優勢是提升軟件的複用性和易維護展性。是面向對象的最基本原則。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(); } }
好到這裏咱們的依賴倒置原則就講完了,總結一下整體原則就是面向接口編程,或者說面向抽象編程。上面例子中的接口咱們也可使用抽象類來代替。同窗們可使用抽象類模擬一下上面的過程。