依賴反轉原則(Dependency Inversion Principle, DIP)
Robert C. Martin 為這個原則提出兩條互相呼應的規則: High-level modules should not import anything from low-level modules. Both should depend on abstractions(高階模組不應依賴低階模組,兩者都應依賴抽象)。 Abstractions should not depend on details. Details should depend on abstractions(抽象不應依賴細節,細節應依賴抽象)。 這兩條規則合在一起,描述的是系統中依賴關係的方向性應該如何安排,要理解它們需要先理解「高階模組」和「低階模組」的差別。 高階模組與低階模組 高階模組(High-level modules):包含應用程式核心業務邏輯的模組,它們描述的是「這個系統要做什麼」:訂單需要被驗證、付款需要被處理、報表需要被產生;這些邏輯代表了系統存在的根本原因,是具有業務價值的部分。 低階模組(Low-level modules):提供具體技術實作的模組,它們描述的是「這件事具體怎麼做」:資料存到 SQL Server、Email 用 SMTP 發送、圖片存到 S3;這些模組是高階模組的工具,本身通常不含業務價值,可以被替換。 在傳統的依賴方向中,高階模組直接使用(依賴)低階模組: OrderService(高階)→ SqlServerRepository(低階) 這意味著業務邏輯層與具體的資料庫技術「綁死」在一起;若今天想把 SQL Server 換成 PostgreSQL,就必須修改 OrderService 這個本來應該只關心業務規則的類別,DIP 要「反轉」的正是這個依賴方向。 與 OOP 的關係:多型(Polymorphism)與抽象(Abstraction) DIP 的實現依賴抽象與多型,具體的做法是在高階模組與低階模組之間插入一層抽象(介面),讓兩者都依賴這個介面,而非彼此直接依賴。 傳統方向(高耦合): OrderService ─────────────────→ SqlServerRepository (高階) (低階,具體實作) DIP 方向(低耦合): OrderService ──→ IOrderRepository ←── SqlServerRepository (高階) (抽象介面) (低階,具體實作) 在 DIP 的架構下,依賴箭頭的方向發生了「反轉」: ...