抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。高層模塊不應(yīng)該依賴于底層模塊,都應(yīng)該依賴的抽象。
依賴反轉(zhuǎn)原則主要想告訴我們的是,如果想設(shè)計一個靈活的系統(tǒng),在源代碼層次的依賴關(guān)系中就應(yīng)該多引用抽象類型,而非具體類型。
- 穩(wěn)定的抽象層
每次修改抽象層的時候,一定也會去修改對應(yīng)的具體實(shí)現(xiàn)。但是反過來,當(dāng)我們修改具體的實(shí)現(xiàn)的時候,卻很少需要去修改相應(yīng)的抽象接口。所以接口比實(shí)現(xiàn)更穩(wěn)定。
依賴守則
應(yīng)在代碼中多使用抽象接口,盡量避免使用那些多變的具體實(shí)現(xiàn)類。
抽象工廠設(shè)計模式
不要在具體實(shí)現(xiàn)類上創(chuàng)建衍生類
面向?qū)ο蟮木幊讨?,繼承關(guān)系是所有以前源代碼依賴關(guān)系中最強(qiáng)的、最難被修改的,所以我們對繼承的使用應(yīng)該格外小心。
不要覆蓋包含具體實(shí)現(xiàn)的函數(shù)
調(diào)用包含具體實(shí)現(xiàn)的函數(shù)通常意味著引入了源代碼級別的依賴。即使覆蓋了這些函數(shù),也無法消除這些依賴關(guān)系。控制依賴關(guān)系的唯一辦法就是使用抽象函數(shù),然后再為該函數(shù)提供多種具體實(shí)現(xiàn)
應(yīng)避免在代碼中寫入與任何具體實(shí)現(xiàn)相關(guān)的名字,或者是其他容易變動的事務(wù)的名字。
創(chuàng)建對象為例
我們必須對那些易變對象的創(chuàng)建過程做一些特殊處理,創(chuàng)建對象的操作都避免不了需要在源代碼層次上依賴對象的具體實(shí)現(xiàn)。在大部分面向?qū)ο缶幊陶Z言中,人們會選擇用抽象工廠模式來解決這個源代碼依賴的問題。

Application類通過Service接口來使用ConcreteImpl類的。然而Application類還是必須要構(gòu)造ConcreteImpl類實(shí)例。為了避免在代碼層次上對引入ConcreteImpl類具體實(shí)現(xiàn)的依賴,現(xiàn)在讓Application類去調(diào)用ServiceFactory接口的makeSvc方法。這個方法就由ServiceFactoryImpl類具體提供,它是ServiceFactory的一個衍生類。ServiceFactoryImpl類中makeSvc的具體實(shí)現(xiàn)就是提供一個ConcreteImpl類的實(shí)例。
圖中那條曲線表示軟件架構(gòu)中抽象層與具體實(shí)現(xiàn)層的邊界。這里所有跨越這條邊界的代碼級別的依賴關(guān)系都應(yīng)該是單向,即具體實(shí)現(xiàn)層依賴抽象層。
這條曲線將整個系統(tǒng)劃分為兩部分組件:抽象接口與其具體實(shí)現(xiàn)。抽象接口組件中包含了應(yīng)用的所有高階業(yè)務(wù)規(guī)則,而具體實(shí)現(xiàn)組件中則包含了所有這些業(yè)務(wù)規(guī)則需要做的具體操作及其相關(guān)細(xì)節(jié)信息。
這里控制跨越架構(gòu)邊界的方向與源代碼依賴關(guān)系跨越該邊界的方向正好相反,源代碼依賴方向永遠(yuǎn)是控制流方向的反轉(zhuǎn)。