聊聊設(shè)計(jì)模式原則(三) -- 依賴倒置原則

目錄

依賴倒置原則(DIP :Dependence Inversion Principle)

定義

  • 高層模塊不應(yīng)該依賴低層模塊呻袭,二者都應(yīng)該依賴其抽象简僧;
  • 抽象不應(yīng)該依賴細(xì)節(jié);
  • 細(xì)節(jié)應(yīng)該依賴抽象。
也就是說(shuō)高層模塊,低層模塊,細(xì)節(jié)都應(yīng)該依賴抽象

由來(lái)

類(lèi)A直接依賴類(lèi)B鄙币,假如要將類(lèi)B改為類(lèi)C,則必須通過(guò)修改類(lèi)A的代碼來(lái)達(dá)成蹂随。
類(lèi)A一般是高層模塊爱榔,負(fù)責(zé)復(fù)雜的業(yè)務(wù)邏輯。
類(lèi)B和類(lèi)C是低層模塊糙及,負(fù)責(zé)基本的原子操作详幽。
修改類(lèi)A,會(huì)給程序帶來(lái)不必要的風(fēng)險(xiǎn)浸锨。

由來(lái)

解決方案

將類(lèi)A修改為依賴接口I唇聘,類(lèi)B和類(lèi)C各自實(shí)現(xiàn)接口I,類(lèi)A通過(guò)接口I間接與類(lèi)B或者類(lèi)C發(fā)生聯(lián)系柱搜,則會(huì)大大降低修改類(lèi)A的幾率迟郎。

解決方案

優(yōu)點(diǎn)

依賴倒置原則可以減少類(lèi)間的耦合性,提高系統(tǒng)的穩(wěn)定聪蘸,降低并行開(kāi)發(fā)引起的風(fēng)險(xiǎn)宪肖,提高代碼的可讀性和可維護(hù)性表制。

思考

1.依賴倒置原則跟面向接口編程是什么關(guān)系?

依賴倒置原則的核心思想就是面向接口編程

2.什么是細(xì)節(jié)控乾?什么是抽象么介?他們有什么區(qū)別?

所謂細(xì)節(jié)就是較為具體的東西蜕衡,比如具體的類(lèi)壤短,就如上面的類(lèi)B與類(lèi)C,有具體的實(shí)現(xiàn)慨仿。

所謂抽象就是具有契約性久脯、共同性、規(guī)范性的表達(dá)镰吆,比如上面的接口I帘撰。它表達(dá)了一種契約--你需要實(shí)現(xiàn)funcA和funcB才能被當(dāng)成I來(lái)對(duì)待。

相對(duì)于細(xì)節(jié)的多變性万皿,抽象的東西要穩(wěn)定的多吟策。
以上面的類(lèi)ABC作為例子笆呆,B整慎、C類(lèi)都屬于細(xì)節(jié)款咖,如果A直接依賴B或者C,那么B或C的改動(dòng)有可能就會(huì)影響到A的穩(wěn)定性唤衫。同樣的婆赠,A對(duì)B或者C的操作也有可能影響到B或C的穩(wěn)定性。這些互相影響佳励,其實(shí)來(lái)源于直接的依賴休里,導(dǎo)致B或C的細(xì)節(jié)暴露過(guò)多。而面對(duì)抽象的接口I赃承,A只能操作funA和funcB妙黍,從而避免了不必要的暴露和風(fēng)險(xiǎn)。

以抽象為基礎(chǔ)搭建起來(lái)的架構(gòu)比以細(xì)節(jié)為基礎(chǔ)搭建起來(lái)的架構(gòu)要穩(wěn)定的多瞧剖。
穩(wěn)定性表現(xiàn)在規(guī)范性拭嫁、契約性、易修改性抓于、擴(kuò)展性做粤、可維護(hù)性等。

來(lái)個(gè)栗子

小明(程序員)接到小李(產(chǎn)品經(jīng)理)的需求:
客戶端開(kāi)始的時(shí)候打個(gè)“開(kāi)始”的log捉撮。
小明心想簡(jiǎn)單怕品,一下子完成了代碼

public class Logger {
    func log(_ text: String) {
        print(text)
    }
}

public class Client {
    public var logger: Logger?

    func start() {
        logger?.log("開(kāi)始")
    }
}

let client = Client()
let logger = Logger()
client.logger = logger

client.start()

這個(gè)時(shí)候,小李突然說(shuō)巾遭,要把log變成存到文件的形式肉康。
小明想了下闯估,有點(diǎn)不情愿地改了代碼(因?yàn)橐暮脦讉€(gè)地方)

public class FileLogger { //修改1
    func log(_ text: String) {
        writeTofile(text) //修改2
    }
    
    func start() {
        print("開(kāi)始")
    }
}

public class Client {
    public var logger: FileLogger? //修改3

    func start() {
        logger.start()
        logger?.log("開(kāi)始")
    }
}

let client = Client()
let logger = FileLogger() //修改4
client.logger = logger

client.start()

小李想了想現(xiàn)在是互聯(lián)網(wǎng)時(shí)代,還是直接將log信息傳到網(wǎng)絡(luò)上吧吼和。
這個(gè)時(shí)候涨薪,小明非常不情愿地說(shuō)了聲“你不早說(shuō)”,但還是改了代碼(又是好幾處改動(dòng))

public class WebLogger { //修改1
    func log(_ text: String) {
        writeToWeb(text) //修改2
    }
}

public class Client {
    public var logger: WebLogger? //修改3

    func start() {
        logger?.log("開(kāi)始")
    }
}

let client = Client()
let logger = WebLogger() //修改4
client.logger = logger

client.start()

這時(shí)纹安,小明的老大小華看到小明不開(kāi)心,便過(guò)來(lái)幫忙砂豌,改了下代碼

protocol Logger {
    func log(_ text: String)
}

public class WebLogger: Logger {
    func log(_ text: String) {
        writeToWeb(text) 
    }
}

public class FileLogger: Logger {
    func log(_ text: String) {
        writeTofile(text) 
    }
}

public class PrintLogger: Logger {
    func log(_ text: String) {
        print(text)
    }
}

public class Client {
    public var logger: Logger? 

    func start() {
        logger?.log("開(kāi)始")
    }
}

let client = Client()
let logger = WebLogger()
client.logger = logger

client.start()

小華對(duì)小明說(shuō)厢岂,現(xiàn)在不用怕了,小李想什么樣的log你改一下實(shí)現(xiàn)類(lèi)就行了

let logger = WebLogger() // PrintLogger()  FileLogger()

小華的改動(dòng)其實(shí)就是利用了依賴倒置原則阳距,增強(qiáng)了易修改性塔粒、擴(kuò)展性、可維護(hù)性等筐摘。
細(xì)心的朋友其實(shí)還發(fā)現(xiàn)了卒茬,在改成FileLogger的時(shí)候,Client多余地調(diào)用了FileLogger的start方法咖熟。這就是依賴細(xì)節(jié)圃酵,暴露細(xì)節(jié),引起的問(wèn)題馍管。而使用抽象的接口就能較好地避免這類(lèi)問(wèn)題郭赐。

注意點(diǎn)

  • 分清細(xì)節(jié)與抽象
    雖然依賴倒置原則有很大的好處,但也不是所有的類(lèi)都需要有抽象一個(gè)接口去對(duì)應(yīng)确沸,要視情況而定捌锭。

  • 變量的聲明類(lèi)型盡量是抽象類(lèi)或接口
    注意是盡量,而不是全部罗捎。

  • 盡量不要覆寫(xiě)基類(lèi)的方法
    如果基類(lèi)是一個(gè)抽象類(lèi)观谦,而這個(gè)方法已經(jīng)實(shí)現(xiàn)了,子類(lèi)盡量不要覆寫(xiě)桨菜。類(lèi)間依賴的是抽象豁状,覆寫(xiě)了抽象方法,對(duì)依賴的穩(wěn)定性會(huì)有一定的影響倒得。

  • 繼承要遵循里氏替換原則

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末替蔬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屎暇,更是在濱河造成了極大的恐慌承桥,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件根悼,死亡現(xiàn)場(chǎng)離奇詭異凶异,居然都是意外死亡蜀撑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)剩彬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)酷麦,“玉大人,你說(shuō)我怎么就攤上這事喉恋∥秩模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵轻黑,是天一觀的道長(zhǎng)糊肤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)氓鄙,這世上最難降的妖魔是什么馆揉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮抖拦,結(jié)果婚禮上升酣,老公的妹妹穿的比我還像新娘。我一直安慰自己态罪,他們只是感情好噩茄,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著复颈,像睡著了一般巢墅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上券膀,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天君纫,我揣著相機(jī)與錄音,去河邊找鬼芹彬。 笑死蓄髓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的舒帮。 我是一名探鬼主播会喝,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼玩郊!你這毒婦竟也來(lái)了肢执?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤译红,失蹤者是張志新(化名)和其女友劉穎预茄,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體侦厚,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耻陕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年拙徽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诗宣。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡膘怕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出召庞,到底是詐尸還是另有隱情岛心,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布篮灼,位于F島的核電站忘古,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏穿稳。R本人自食惡果不足惜存皂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一晌坤、第九天 我趴在偏房一處隱蔽的房頂上張望逢艘。 院中可真熱鬧,春花似錦骤菠、人聲如沸它改。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)央拖。三九已至,卻和暖如春鹉戚,著一層夾襖步出監(jiān)牢的瞬間鲜戒,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工抹凳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留遏餐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓赢底,卻偏偏與公主長(zhǎng)得像失都,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子幸冻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345