軟體架構設計原則之依賴倒置原則
依賴倒置原則(Dependence Inversion Principle,DIP)是指設計程式碼結構時,高層模組不應該依賴低層模組,二者都應該依賴其抽象。抽象不應該依賴細節,細節應該依賴抽象。通過依賴倒置,可以減少類與類之間的耦合性,提高系統的穩定性,提高程式碼的可讀性和可維護性,並且能夠降低修改程式所造成的風險。接下來看一個案例,還是以Course(課程)為例,先來建立一個類Tom:
public class Tom { public void studyJavaCourse(){ System.out.println("Tom在學習Java的課程"); } public void studyPythonCourse(){ System.out.println("Tom在學習Python的課程"); } }
來呼叫一下:
public static void main(String[] args) {
Tom tom = new Tom();
tom.studyJavaCourse();
tom.studyPythonCourse();
}
Tom熱愛學習,目前正在學習Java課程和Python課程。大家都知道,學習也是會上癮的。隨著學習興趣的“暴漲”,現在Tom還想學習AI(人工智慧)的課程。這時候,因為業務擴充套件,要從低層到高層(呼叫層)依次修改程式碼。在Tom類中增加studyAICourse()方法,在高層也要追加呼叫。如此一來,系統釋出以後,實際上是非常不穩定的,在修改程式碼的同時也會帶來意想不到的風險。接下來我們優化程式碼,建立一個課程的抽象ICourse介面:
public interface ICourse {
void study();
}
然後編寫JavaCourse類:
public class JavaCourse implements ICourse {
@Override
public void study() {
System.out.println("Tom在學習Java課程");
}
}
再實現PythonCourse類:
public class PythonCourse implements ICourse { @Override public void study() { System.out.println("Tom在學習Python課程"); } }
修改Tom類:
public class Tom {
public void study(ICourse course){
course.study();
}
}
來看呼叫程式碼:
public static void main(String[] args) {
Tom tom = new Tom();
tom.study(new JavaCourse());
tom.study(new PythonCourse());
}
這時候再看來程式碼,Tom的興趣無論怎麼暴漲,對於新的課程,只需要新建一個類,通過傳參的方式告訴Tom,而不需要修改底層程式碼。實際上這是一種大家非常熟悉的方式,叫依賴注入。注入的方式還有構造器方式和Setter方式。我們來看構造器注入方式:
public class Tom {
private ICourse course;
public Tom(ICourse course){
this.course = course;
}
public void study(){
course.study();
}
}
看呼叫程式碼:
public static void main(String[] args) {
Tom tom = new Tom(new JavaCourse());
tom.study();
}
根據構造器方式注入,在呼叫時,每次都要建立例項。如果Tom是全域性單例,則我們就只能選擇用Setter方式來注入,繼續修改Tom類的程式碼:
public class Tom {
private ICourse course;
public void setCourse(ICourse course) {
this.course = course;
}
public void study(){
course.study();
}
}
看呼叫程式碼:
public static void main(String[] args) {
Tom tom = new Tom();
tom.setCourse(new JavaCourse());
tom.study();
tom.setCourse(new PythonCourse());
tom.study();
}
現在我們再來看最終的類圖,如下圖所示。
大家要切記:以抽象為基準比以細節為基準搭建起來的架構要穩定得多,因此在拿到需求之後,要面向介面程式設計,先頂層再細節地設計程式碼結構。
本文為“Tom彈架構”原創,轉載請註明出處。技術在於分享,我分享我快樂!
如果本文對您有幫助,歡迎關注和點贊;如果您有任何建議也可留言評論或私信,您的支援是我堅持創作的動力。關注微信公眾號“Tom彈架構”可獲取更多技術乾貨!