所謂開閉原則就是一個軟件實體如類、模塊和函數應該對擴展開放、對修改關閉。 強調用抽象構建框架,實現實現拓展細節。前端
有優勢是提升軟件的複用性和易維護展性。是面向對象的最基本原則。java
高層模塊不該該依賴底層模塊,兩者都應該依賴其抽象。 抽象不該該依賴細節:細節應該依賴抽象。 針對接口編程,不要針對實現編程。編程
下降耦合提升穩定性,提升代碼的可讀性和易維護性。減小代碼在修改時可能形成的風險。bash
下面咱們用代碼來講明啥是依賴倒置原則框架
假設咱們想實現一我的在學習的需求,咱們能夠這樣寫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類修改成以下,這裏注意這個方法的類型是用接口類型,不是具體類類型,在調用這個方法時,接口類型會根據實體類的類型向下轉型執行具體方法。
/** * @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();
}
}
複製代碼
好到這裏咱們的依賴倒置原則就講完了,總結一下整體原則就是面向接口編程,或者說面向抽象編程。上面例子中的接口咱們也可使用抽象類來代替。同窗們可使用抽象類模擬一下上面的過程。