英文原文:How I explained OOD to my wife我是怎樣教媳婦面向?qū)ο缶幊痰?br>
我老婆 Farhana 想要繼續(xù)軟件開發(fā)生涯(之前因?yàn)槲覀兊牡谝粋€(gè)孩子出生,她不得不放棄)。我已經(jīng)有了一些軟件設(shè)計(jì)和開發(fā)的經(jīng)驗(yàn)兼蕊,所以這幾天我就在試著幫助她學(xué)習(xí)OOD奠支。
由于我早年在軟件開發(fā)的經(jīng)驗(yàn)窘游,我總是發(fā)現(xiàn)無論一個(gè)技術(shù)問題看上去多么難搞乘综,只要從現(xiàn)實(shí)生活的角度去解釋或用對話的方式去討論總能讓它變得更簡單祭埂。關(guān)于OOD舅巷,我們已經(jīng)有了許多成果豐碩的討論羔味,我覺得有人可能發(fā)現(xiàn)這是一個(gè)學(xué)習(xí)OOD有趣的方式,所以我想我應(yīng)該分享出來钠右。
下面是我們的談話步驟:
話題:介紹面向?qū)ο笤O(shè)計(jì)
丈夫:親愛的赋元,讓我們開始學(xué)習(xí)面向?qū)ο笤O(shè)計(jì)。你了解面向?qū)ο笠?guī)范飒房,對嗎搁凸?
妻子:你是指封裝,繼承和多態(tài)嗎狠毯?是的护糖,我了解這些規(guī)范。
丈夫:行嚼松,我想你已經(jīng)知道怎么用類和對象了椅文。今天我們來學(xué)習(xí)面向?qū)ο笤O(shè)計(jì)。
妻子:等等惜颇。了解面向?qū)ο笠?guī)范對面向?qū)ο缶幊虂碚f難道不夠嗎皆刺?我的意思是,我能夠定義類凌摄,封裝屬性和方法羡蛾。我能夠根據(jù)它們的關(guān)系定義類的繼承。那還有什么呢锨亏?
丈夫:很好的問題痴怨。面向?qū)ο笠?guī)范和面向?qū)ο缶幊掏耆莾纱a事。讓我展示一個(gè)現(xiàn)實(shí)生活中的例子來幫助你理解它們器予。
我們從牙牙學(xué)語起浪藻,都是先從字母表學(xué)起的,對吧乾翔?
妻子: 嗯爱葵。
丈夫: 好施戴,然后你就能認(rèn)單詞了,還能通過不同的字母拼寫出不同的單詞來萌丈。慢慢的赞哗,你能通過一些基本的語法把這些單詞串成一句話。為了使句子時(shí)態(tài)正確且沒有語病辆雾,你需要用一些介詞肪笋,連詞,等等度迂。藤乙。看下面這句話
"I" (代詞) "want" (動詞) "to" (介詞) "learn" (動詞) "OOD" (名詞)
通過把幾個(gè)單詞擺放妥當(dāng)一句話就好了惭墓,然后用個(gè)關(guān)鍵詞來說明一下這句話的重點(diǎn)湾盒。
妻子: 親愛的,你閑扯這些到底要說明什么呢
丈夫: 我說的這個(gè)例子跟面向?qū)ο笠?guī)范很類似诅妹,面向?qū)ο笠?guī)范為面向?qū)ο缶幊潭x了基本的規(guī)范罚勾,它是面向?qū)ο缶幊痰闹饕枷搿C嫦驅(qū)ο笠?guī)范好比基本的英語語法吭狡,這些語法教會了你怎么用一個(gè)個(gè)單詞拼湊出一句句話來尖殃,而面向?qū)ο缶幊探棠阍趺从妙悾趺窗岩恍傩院头椒ǚ庋b在一個(gè)類里划煮,怎么串出類之間的繼承關(guān)系送丰。
妻子: 啊哈,我知道了弛秋,那么器躏,面向?qū)ο筮m用于哪里呢。
丈夫: 聽我慢慢道來⌒仿裕現(xiàn)在登失,假設(shè)你想寫點(diǎn)有內(nèi)容有題材的文章。你當(dāng)然還希望寫點(diǎn)你比較擅長的題材的書挖炬,就會簡單造幾個(gè)句子是遠(yuǎn)遠(yuǎn)不夠的揽浙,對吧。你需要筆耕不輟寫出一些長篇大論意敛,你還需要學(xué)習(xí)怎么可以讓讀者很容易就看懂你寫的這些長篇大論馅巷。。草姻。
妻子:嗯钓猬,有那么點(diǎn)意思。撩独。敞曹。繼續(xù)吧
丈夫:現(xiàn)在账月,假如你想寫本關(guān)于面向?qū)ο笤O(shè)計(jì)的書,你需要把這個(gè)大的課題拆分成一些小題目异雁。把這些小題目分幾個(gè)章節(jié)寫捶障,還得寫前言僧须,簡介纲刀,說明,舉例担平,一篇里還有很多段落示绊。你需要設(shè)計(jì)一整本書,還得練習(xí)一些寫作技巧暂论,讓文章讀起來淺顯易懂面褐。這就是綜觀全局。
在軟件開發(fā)中取胎,OOD就是用來解決從全局出發(fā)考慮問題展哭,在設(shè)計(jì)軟件的時(shí)候,類和代碼可以模塊化闻蛀,可重復(fù)使用匪傍,可靈活應(yīng)用,現(xiàn)在已經(jīng)有很多前人總結(jié)出的類和對象的設(shè)計(jì)原理了觉痛,我們直接拿來用就行了役衡,總之,歷史的車輪已經(jīng)碾壓出一條清晰的車輪印薪棒,我們只要照著走就可以了手蝎。
妻子: 哎,懂了點(diǎn)皮毛俐芯,還有很多要學(xué)呢棵介。
丈夫:不用擔(dān)心,你很快就會上手的吧史,讓我們接著來吧鞍时。
話題:為什么要進(jìn)行面向?qū)ο笤O(shè)計(jì)?
作者:有個(gè)很重要的問題扣蜻,既然我們能夠很快的創(chuàng)建幾個(gè)類逆巍,編寫程序并提交,為什么我們還要關(guān)注面向?qū)ο笤O(shè)計(jì)莽使?這樣不夠么锐极?
妻子:恩,以前我不知道面向?qū)ο笤O(shè)計(jì)芳肌,我也能開發(fā)提交項(xiàng)目灵再。有什么關(guān)系肋层?
丈夫:好吧,先讓我給你看一個(gè)經(jīng)典的引述:
"需求不變的程序開發(fā)會同行走在冰上一樣簡單翎迁。" - Edward V. Berard
妻子:你是指軟件開發(fā)說明書會被不斷修改栋猖?
丈夫:非常正確!軟件開發(fā)唯一的真理是“軟件必然修改”。為什么?
要知道汪榔,你的軟件解決的是現(xiàn)實(shí)世界中的問題蒲拉,而現(xiàn)實(shí)生活不是一成不變的。
可能你的軟件現(xiàn)在運(yùn)行良好痴腌。但它能靈活的支持“變化”嗎雌团?如果不能,那它就不是一個(gè)敏捷設(shè)計(jì)的軟件士聪。
妻子:好锦援,那你就解釋一下什么叫做“敏捷設(shè)計(jì)的軟件”!
丈夫:“一個(gè)敏捷設(shè)計(jì)的軟件能輕松應(yīng)對變化剥悟,能被擴(kuò)展和復(fù)用灵寺。”
而應(yīng)用“面向?qū)ο笤O(shè)計(jì)”是做到敏捷設(shè)計(jì)的關(guān)鍵区岗。那么略板,什么時(shí)候你可以說你的程序應(yīng)用了面向?qū)ο笤O(shè)計(jì)?
妻子:我也正想問呢躏尉。
丈夫:如果代碼符合以下幾點(diǎn)蚯根,那么你就在“面向?qū)ο笤O(shè)計(jì)”:
面向?qū)ο螅粡?fù)用胀糜;變化的代價(jià)極新埂;無需改代碼即可擴(kuò)展
妻子:然后呢教藻?
丈夫:不只我們距帅。很多人也花了很多時(shí)間和精力思考這個(gè)問題上,他們嘗試更好的進(jìn)行“面向?qū)ο笤O(shè)計(jì)”括堤,并為“面向?qū)ο笤O(shè)計(jì)”指出幾條基本的原則(你可以用在你的“面向?qū)ο笤O(shè)計(jì)”中)碌秸。他們也確實(shí)總結(jié)出了一些通用的設(shè)計(jì)模式(基于基本的原則)。
妻子:你能說出一些嗎悄窃?
丈夫:沒問題〖サ纾現(xiàn)在有許多設(shè)計(jì)原則,但是最基本的轧抗,就是SOLID(縮寫)恩敌,這五項(xiàng)原則。(感謝鮑勃叔叔横媚,偉大OOD導(dǎo)師)纠炮。
- S = 單一責(zé)任原則
- O = 開閉原則
- L = Liscov替換原則
- I = 接口隔離原則
- D = 依賴倒置原則
- 在下面的討論中月趟,我們將詳細(xì)了解這些。
話題:單一功能原則
作者:讓我們先來看圖恢口,我們應(yīng)該感謝制作這張圖的人孝宗,因?yàn)樗鼈冋娴奶腥ち恕?br>
單一功能原則圖
它的意思是:“如果你可以在一個(gè)設(shè)備中實(shí)現(xiàn)所有的功能,你卻不能這樣做”耕肩。為什么呢因妇?因?yàn)閺拈L遠(yuǎn)來看它增加了很多的可管理性問題。
從面向?qū)ο蠼嵌冉忉屖牵?br>
"導(dǎo)致類變化的因素永遠(yuǎn)不要多于一個(gè)看疗。"
或者換行個(gè)說法:"一個(gè)類有且只有一個(gè)職責(zé)"沙峻。
妻子:可以解釋一下么睦授?
丈夫:當(dāng)然两芳,這個(gè)原則是說,如果有多于一個(gè)原因會導(dǎo)致你的類改變(或者它的職責(zé)多余一個(gè))去枷,你就需要根據(jù)其職責(zé)把這個(gè)類拆分為多個(gè)類怖辆。
妻子:嗯...這是不是意味著在一個(gè)類里不能有多個(gè)方法?
丈夫:當(dāng)然不是删顶。你當(dāng)然可以在一個(gè)類中包含多個(gè)方法竖螃。問題是,他們都是為了一個(gè)目的逗余。那么特咆,為什么拆分很重要的?
那是因?yàn)椋?br>
每個(gè)職責(zé)都是軸向變化;
如果類包含多個(gè)職責(zé)录粱,代碼會變得耦合;
妻子:給個(gè)例子唄腻格?
丈夫:木有問題啊,瞅瞅下面類的結(jié)構(gòu)啥繁。其實(shí)菜职,這個(gè)例子是 Bob 叔叔那兒來的,得謝謝他旗闽。
違反SRP原則的類層次結(jié)構(gòu)
這里酬核,Rectangle 類干了下面兩件事:
計(jì)算矩形面積; 在界面上繪制矩形;
而且,有兩個(gè)程序使用了 Rectangle 類:
計(jì)算幾何應(yīng)用程序用這個(gè)類計(jì)算面積; 圖形程序用這個(gè)類在界面上繪制矩形;
這違反了SRP原則(單一職責(zé)原則)!
妻子:腫么回事适室?
丈夫:你瞅瞅嫡意,Rectangle 類干了倆不相干的事。一個(gè)方法它計(jì)算了面積捣辆,另外一個(gè)它返回一個(gè)表示矩形的 GUI 資源蔬螟。這問題就有點(diǎn)樂了:
在計(jì)算幾何應(yīng)用程序里咱得包著 GUI。就是說罪帖,寫幾何應(yīng)用代碼促煮,咱也得引用 GUI 庫;
要是為了圖形應(yīng)用所改變 Rectangle 類邮屁,計(jì)算幾何應(yīng)用也可能跟著變,然后還得編譯菠齿,還得測試佑吝,另一邊也是;
妻子:是很樂。就是說绳匀,咱得根據(jù)累的職責(zé)分開寫唄芋忿?
丈夫:必須滴。猜猜怎么干疾棵?
妻子:我想想戈钢,我尋思這得這么辦:
我瞅著得按職責(zé)拆成兩個(gè)類:
Rectangle:這個(gè)類定義 Area() 方法;
RectangleUI:這個(gè)把 Rectangle 類繼承過來,定義 Draw() 方法是尔。
丈夫:很好殉了。這么個(gè),計(jì)算幾何應(yīng)用使 Rectangle 類拟枚,圖形應(yīng)用使 RectangleUI 類薪铜。咱還可以把這倆類分到倆單獨(dú)的 DLL 中,然后改的時(shí)候就不用管另一個(gè)了恩溅。
妻子:謝了隔箍,我大概明白 SRP 原則了一句話:SPR 就是把東西分到不能再分了,再集中化管理和復(fù)用脚乡。囔蜒滩,在方法層面上,咱不也得用 SPR 原則奶稠?我是說俯艰,咱寫的方法里有很多干不同事兒的代碼,這也不符合 SPR原則吧窒典。
丈夫:你說地不差蟆炊。方法也得分開,一個(gè)方法干一個(gè)活瀑志。這么著你復(fù)用方法涩搓,要是改了,也不用改太多劈猪。
話題:開閉原則
圖:開閉原則圖
讓我來解釋一下昧甘,設(shè)計(jì)規(guī)則如下:
“軟件實(shí)體(類,模塊战得,函數(shù)等)應(yīng)該對擴(kuò)展開放充边,對修改關(guān)閉。”
這意味著在最基本的層面上浇冰,你可以擴(kuò)展一個(gè)類的行為贬媒,而無需修改。這就像我能夠穿上衣服肘习,而對我的身體不做任何改變际乘,哈哈。
妻子: 太有意思啦. 你可以通過穿不同的衣服來改變你的外貌, 但是你不必為此改變自己的身體.所以你是對擴(kuò)展開放的, 對吧?
丈夫: 是的. 在面向?qū)ο笤O(shè)計(jì)中, 對擴(kuò)展開放意味著模塊/類的行為可以被擴(kuò)展,那么當(dāng)需求變化時(shí)我們可以用各種各樣的方法制定功能來滿足需求變更或者新需求
妻子: 除此之外你的身體是對修改關(guān)閉的. 我喜歡這個(gè)例子. 所以, 對于核心模塊或類的代碼在需要擴(kuò)展的時(shí)候不應(yīng)該被修改. 你能結(jié)合具體例子解釋下嗎?
丈夫: 當(dāng)然了, 先看下面的例子.這個(gè)就不支持 "開放-關(guān)閉" 原則:
類的層次結(jié)構(gòu)已經(jīng)表明了這是違反"開放-關(guān)閉"原則的.
你看, 客戶端類和服務(wù)端類都是具體的實(shí)現(xiàn)類. 因?yàn)? 如果某些原因?qū)е路?wù)端實(shí)現(xiàn)改變了, 客戶端也需要相應(yīng)變化.
妻子: 有道理. 如果一個(gè)瀏覽器的實(shí)現(xiàn)和一個(gè)指定的服務(wù)器(比如IIS)緊緊的耦合在一起 , 那么如果服務(wù)器由于某種原因替換成了另外的 (比如, Apache) 瀏覽器也需要做相應(yīng)的變化或者被替換掉. 多么恐怖的一件事啊!
丈夫: 非常正確. 因?yàn)橄旅娴膶⑹且环N好的設(shè)計(jì)方案:
類的層次關(guān)系展示了"開放-關(guān)閉"原則
在這個(gè)例子中, 添加了一個(gè)抽象的Server類, 并且客戶端保持了抽象類的引用, 具體的Server類實(shí)現(xiàn)了這個(gè)抽象Server類. 所以, 由于某種原因Server的實(shí)現(xiàn)類發(fā)生了改變, 客戶端不需要做任何改變.
這里的抽象的Server類對修改關(guān)閉, 具體的Server實(shí)現(xiàn)類對擴(kuò)展開放.
妻子: 我的理解是, 抽象是關(guān)鍵, 對嗎?
丈夫: 是的, 基本上, 你要對系統(tǒng)的核心業(yè)務(wù)進(jìn)行抽象, 如果你抽象化做的比較好, 很可能, 在擴(kuò)展功能的時(shí)候它們不必做任何改變 (比如Server就是一個(gè)抽象的概念). 你所定義的抽象的實(shí)現(xiàn) (比如, IIS服務(wù)器 實(shí)現(xiàn)了 Server) 和 抽象的代碼 (Server) 要盡可能的多. 這樣在客戶端代碼中不需要做任何修改就會允許你定義一個(gè)新的實(shí)現(xiàn)(比如, ApacheServer) .
主題: 里氏替換原則
丈夫: "里氏替換原則"聽起來非常的復(fù)雜,但是思想史非称澹基礎(chǔ)的. 看下面這個(gè)有趣的海報(bào)
里氏替換原則海報(bào)
原則描述了:
"子類型必須能夠替換它們的基類."
或者, 換句話說:
"使用基類引用的函數(shù)必須能夠使用派生類而無須了解派生類."
妻子: 對不起, 這聽起來讓我覺得有點(diǎn)亂. 我認(rèn)為這個(gè)是面向?qū)ο缶幊痰幕驹瓌t. 這個(gè)叫做多態(tài)性, 對吧? 為什么面向?qū)ο笤O(shè)計(jì)原則需要考慮這個(gè)問題?
丈夫: 非常好的問題. 這有一些答案:
在基本的面向?qū)ο笤瓌t中, "繼承" 通常被描述成 "is a" 的關(guān)系. 如果一個(gè) "開發(fā)者" 是"軟件專業(yè)人員", 那么 "開發(fā)者" 類 應(yīng)該 繼承 "軟件開發(fā)人員" 類. 這樣的 "Is a" 關(guān)系 在類設(shè)計(jì)階段非常重要, 但是這也很容易讓設(shè)計(jì)者得意忘形從而以一個(gè)糟糕的繼承設(shè)計(jì)告終.
"里氏替換原則" 僅僅是一種確保繼承被正確使用的手段.
妻子:我明白了脖含。真有趣。
丈夫:是的投蝉,親愛的养葵,確實(shí)如此。讓我們來看看一個(gè)例子:
類層次結(jié)構(gòu)圖展示的是一個(gè)Liskov替換原則的例子.因?yàn)?KingFisher類拓展(繼承)了Bird類瘩缆,因此繼承了Fly()這個(gè)方法,這是非常不錯(cuò)的.
我們再來看看下面的例子
修正過的Liskov替換原則的類層次結(jié)構(gòu)圖
Ostrich(鴕鳥)是一種鳥(顯然是)关拒,并繼承了 Bird 類。但它能飛嗎咳榜?不能夏醉,這個(gè)設(shè)計(jì)就違反了里氏替換原則爽锥。
因此涌韩,即使在現(xiàn)實(shí)中看上去沒什么問題,在類設(shè)計(jì)中氯夷,Ostrich 都不應(yīng)該繼承 Bird 類臣樱,而應(yīng)該從 Bird 中分出一個(gè)不會飛的類,由 Ostrich 繼承腮考。
妻子:好吧雇毫,明白了。我說說為什么里氏替換原則如此重要:
如果不遵循 LSP原則踩蔚,類繼承就會混亂棚放。如果子類實(shí)例被作為參數(shù)傳遞給方法,后果難以預(yù)測馅闽。
如果不遵循 LSP原則飘蚯,基于父類編寫的單元測試代碼將無法成功運(yùn)行子類。
我說的對嗎福也?
作者:完全正確局骤,你可以設(shè)計(jì)一個(gè)對象并用LSP作為驗(yàn)證工具來測試該對象是否能夠繼承。
話題:接口隔離原則
作者:今天我們講下“接口隔離原則”暴凑,看看下面這張海報(bào)
接口隔離原則海報(bào)
妻子:這是什么意思峦甩?
作者:它的意思是這樣的:“用戶不應(yīng)該被迫依賴他們不使用的接口∠衷”
妻子:解釋一下凯傲。
作者:好吧犬辰,解釋如下:
假設(shè)你想去買一臺電視機(jī)并且有兩種類型可以選擇,其中一種有很多開關(guān)和按鈕冰单,但是多數(shù)對你來說用不到忧风,另一種只有幾個(gè)開關(guān)和按鈕,并且看來你很熟悉怎么用球凰。如果這兩種電視機(jī)提供同樣的功能狮腿,你會選擇哪一種?
妻子:當(dāng)然是第二種了呕诉。
作者:嗯缘厢,但是為什么呢?
妻子:因?yàn)槲也恍枰雌饋砗苈闊┒覍ξ乙膊槐匾拈_關(guān)和按鈕甩挫。
丈夫:正確贴硫。同樣的,假如你有一些類伊者,你通過接口暴露了類的功能英遭,這樣外部就能夠知道類中可用的功能,客戶端也可以根據(jù)接口來設(shè)計(jì)亦渗。當(dāng)然那挖诸,如果接口太大,或是暴露的方法太多法精,從外部看也會很混亂多律。接口包含的方法太多也會降低可復(fù)用性, 這種包含無用方法的”胖接口“無疑會增加類的耦合搂蜓。
這還會引起其他的問題狼荞。如果一個(gè)類視圖實(shí)現(xiàn)接口,它需要實(shí)現(xiàn)接口中所有的方法帮碰,哪怕一點(diǎn)都用不到相味。所以,這樣會增加系統(tǒng)復(fù)雜度殉挽,降低系統(tǒng)可維護(hù)性和穩(wěn)定性丰涉。
接口隔離原則確保接口實(shí)現(xiàn)自己的職責(zé),且清晰明確此再,易于理解昔搂,具有可復(fù)用性。
妻子:我明白了输拇,你的意思是接口只應(yīng)該包括必要的方法而不是所有的摘符。
作者:是的,讓我們看一個(gè)例子。
下面的接口是一個(gè)“胖接口”逛裤,這違反接口隔離原則:
違反接口隔離原則的接口示例
注意瘩绒,IBird接口定義 Fly()的行為有許多鳥類的行為。現(xiàn)在带族,如果一只鳥類(比方說锁荔,鴕鳥)實(shí)現(xiàn)了這個(gè)接口,它將會實(shí)現(xiàn)不必要的 Fly()的行為(鴕鳥不會飛)蝙砌。
妻子:是啊阳堕。因此,這個(gè)接口必須被分割择克?
作者:是的恬总,“胖接口”應(yīng)該分隔成兩個(gè)不同的接口,IBird 和IFlyingBird肚邢,而IFlyingBird繼承于IBird壹堰。
接口隔離原則的例子中正確版本的接口
如果有一只不會飛的鳥(比如,駝鳥)骡湖,只要用IBird接口即可贱纠,如果有一保會飛的鳥(比如,翠鳥)响蕴,只要用IFlyingBird接口即可谆焊。
妻子:所以,回過頭來看有很多按鈕開關(guān)的電視的例子换途,制造商應(yīng)該有電視機(jī)的圖紙懊渡,開關(guān)和按鈕也在這個(gè)方案里。若他們想造一臺新款電視機(jī)時(shí)想要復(fù)用這張圖紙军拟,他們必須添加更多的按鈕和開關(guān),否則沒法復(fù)用誓禁,對么懈息?
丈夫:對。
妻子:若是他們真的想要復(fù)用這個(gè)方案摹恰,他們應(yīng)該將電視機(jī)的圖紙分為更小的部分辫继,才能在以后制造新款電視機(jī)的時(shí)候復(fù)用這些設(shè)計(jì)方案。
丈夫:你理解了俗慈。
話題:依賴倒置原則
依賴倒置原則圖示
它的意思是:
“高層次的模塊不應(yīng)該依賴于低層次的模塊,而是闺阱,都應(yīng)該依賴于抽象炮车。”
作者:我們用一個(gè)現(xiàn)實(shí)的例子來理解。你的汽車是用很多部件組成仲闽,比如發(fā)動機(jī)絮蒿,車輪爵赵,空調(diào)和其他的部件,是吧绵咱?
妻子:是啊,當(dāng)然是這樣熙兔。
丈夫:你看悲伶,它們并沒有嚴(yán)格的構(gòu)建在一個(gè)部件里;就是說住涉,它們都是“插件”拢切,要是引擎或著車輪出了問題,你可以單獨(dú)修理它秆吵,甚至換一個(gè)用淮椰。
替換時(shí),你只需要保證沉淪符合汽車的設(shè)計(jì)(汽車能使用任何1500CC的引擎或任何18寸的車輪)纳寂。
當(dāng)然主穗,你可以在1500CC 的位置上安裝2000 CC的引擎,對某些制造商都一樣(豐田汽車)毙芜。
可如果你的汽車部件不是“可拔插”的呢忽媒?
妻子:那太可怕了!這樣的話腋粥,要是汽車引擎故障晦雨,你得整車修理,或者買一輛新車隘冲!
丈夫:是的闹瞧,那么怎么做到"可插拔"呢?
妻子:關(guān)鍵是”抽象“展辞,是吧奥邮?
丈夫:對。現(xiàn)實(shí)世界中罗珍,汽車是高層級的模塊/實(shí)體洽腺,它依賴于底層級的模塊/實(shí)體,例如引擎和輪子覆旱。
相較于直接依賴于實(shí)體的引擎或輪子蘸朋,汽車應(yīng)該依賴于抽象的引擎或輪子的規(guī)格,這樣只要是符合這個(gè)抽象規(guī)格的引擎或輪子扣唱,都可以裝到車?yán)锱堋?br>
來看看下面的圖:
依賴倒置原則的類層次結(jié)構(gòu)
丈夫:注意上面的 Car類藕坯,它有兩個(gè)屬性团南,且都是抽象類型(接口)而非實(shí)體的。
引擎和車輪是可插拔的堕担,這樣汽車能接受任何實(shí)現(xiàn)了聲明接口的對象已慢,且 Car 類無需任何改動。
妻子:所以霹购,如果代碼不遵循依賴倒置佑惠,就有下面的風(fēng)險(xiǎn):
使用低層級類會破環(huán)高層級代碼;
當(dāng)?shù)蛯蛹壍念愖兓瘯r(shí)齐疙,需要太多時(shí)間和代價(jià)來修改高層級代碼膜楷;
代碼可復(fù)用性不高
丈夫:親愛的,你說到點(diǎn)子上了贞奋!
總結(jié)
丈夫:除 SOLID 原則外還有很多別的面向?qū)ο笤瓌t赌厅。比如:
“組合替代繼承”:是說“用組合比用繼承好”;
“笛米特法則”:是說“類對其它類知道的越少越好”;
“共同封閉原則”:是說“相關(guān)類應(yīng)該一起打包”;
“穩(wěn)定抽象原則”:這是說"類越穩(wěn)定,就越應(yīng)該是抽象類";
妻子:我得學(xué)習(xí)這些原則嗎轿塔?
丈夫:當(dāng)然了特愿。你可以在網(wǎng)上學(xué)習(xí)。Google 它勾缭,學(xué)習(xí)它揍障,理解它。有問題就找我俩由。
妻子:我聽說還有些根據(jù)設(shè)計(jì)原則編寫的設(shè)計(jì)模式毒嫡。
丈夫:對的。設(shè)計(jì)模式不過就是針對一些經(jīng)常出現(xiàn)的場景的一些通用的設(shè)計(jì)建議幻梯。主要的想法還是面向?qū)ο笤瓌t兜畸。你可以認(rèn)為設(shè)計(jì)模式是“框架”,OOD 原則是“規(guī)范”。
妻子:那么之后我將學(xué)習(xí)設(shè)計(jì)模式是吧碘梢?
丈夫:是的咬摇,親愛的。
妻子:應(yīng)該會很有意思痘系。
丈夫:必須地菲嘴!