依賴倒置:就是要依賴於抽象,不要依賴於具體。簡單的說就是要求對抽象進行編程,不要對實現進行編程,這樣就降低了客戶與實現模塊間的耦合。
假設一個客戶端可以根據不同的終端智能顯示,面向過程的處理流程結構圖如下:
客戶端代碼流程如下:
if (type == Teminal1) { T1_disply(); } else if(type == Teminal2) { T2_disply(); }
功能實現沒有任何問題,考慮到軟件的擴展如果增加一個新的終端我們再客戶端的流程中就要加一個判斷分支,如果系統夠復雜后果往往是在流程中遍布判斷,對后期的開發、維護都是艱巨的任務。產生這種結果的原因是業務依賴了底層的具體實現,兩者完全耦合在一起。我們需要依賴一個穩定的接口。在面向對象的語言比如JAVA,接口在語言級別都是支持的,實現起來相對直觀,但只要理解了設計的本質,在C中實現接口依賴也很容易。修改一下設計,在業務和底層間增加一個接口層:
代碼流程如下:
1:接口定義:
/*ITerminal.h*/
typedef struct Terminal_s Terminal_t; struct Terminal_s { void (*display)(); };
2:終端實現:
#include "ITerminal.h" void Terminal1_display() { printf("Terminal1_display \r\n"); } Terminal_t init_Terminal1() { Terminal_t t; t.display = Terminal1_display; return t; }
3:客戶端:
Terminal_t t; t = init_Terminal1(); t.display();
可以看到我們在業務層和底層間定義了ITerminal.h這個接口層,業務和底層都依賴這個接口,如果新增了終端在客戶端完全感知不到,客戶端只知道display這個接口。
業務中的主流程通常是高層模塊,當高層依賴底層時一定不能讓底層的修改影響到高層,否則業務的主流程將變得臃腫不堪,而依賴倒置原則可以很好的解決這個問題。