如何向妻子解释OOD(转)
前言
此文譯自CodeProject上<How I explained OOD to my wife>一文,該文章在Top Articles上排名第3,讀了之后覺(jué)得非常好,就翻譯出來(lái),供不想讀英文的同學(xué)參考學(xué)習(xí)。
作者(Shubho)的妻子(Farhana)打算重新做一名軟件工程師(她本來(lái)是,后來(lái)因?yàn)樗麄兒⒆映錾艞壛?,于是作者就試圖根據(jù)自己在軟件開(kāi)發(fā)設(shè)計(jì)方面的經(jīng)驗(yàn)幫助她學(xué)習(xí)面向?qū)ο笤O(shè)計(jì)(OOD)。
自作者從事軟件開(kāi)發(fā)開(kāi)始,作者常常注意到不管技術(shù)問(wèn)題看起來(lái)多復(fù)雜,如果從現(xiàn)實(shí)生活的角度解釋并以對(duì)答的方式討論,那么它將變得更簡(jiǎn)單?,F(xiàn)在他們把在OOD方面有些富有成效的對(duì)話分享出來(lái),你可能會(huì)發(fā)現(xiàn)那是一種學(xué)習(xí)OOD很有意思的方式。
下面就是他們的對(duì)話:
OOD簡(jiǎn)介
Shubho:親愛(ài)的,讓我們開(kāi)始學(xué)習(xí)OOD吧。你了解面向?qū)ο笤瓌t嗎?
Farhana:你是說(shuō)封裝,繼承,多態(tài)對(duì)嗎?我知道的。
Shubho:好,我希望你已了解如何使用類(lèi)和對(duì)象。今天我們學(xué)習(xí)OOD。
Farhana:等一下。面向?qū)ο笤瓌t對(duì)面向?qū)ο缶幊?OOP)來(lái)說(shuō)不夠嗎?我的意思是我會(huì)定義類(lèi),并封裝屬性和方法。我也能根據(jù)類(lèi)的關(guān)系定義它們之間的層次。如果是,那么還有什么?
Shubho:問(wèn)得好。面向?qū)ο笤瓌t和OOD實(shí)際上是兩個(gè)不同的方面。讓我給你舉個(gè)實(shí)際生活中的例子幫你弄明白。
?再你小時(shí)候你首先學(xué)會(huì)字母表,對(duì)嗎?
Farhana:嗯
Shubho:好。你也學(xué)了單詞,并學(xué)會(huì)如何根據(jù)字母表造詞。后來(lái)你學(xué)會(huì)了一些造句的語(yǔ)法。例如時(shí)態(tài),介詞,連詞和其他一些讓你能造出語(yǔ)法正確的句子。例如:
"I" (代詞) "want" (動(dòng)詞) "to" (介詞) "learn" (動(dòng)詞) "OOD"(名詞)。
看,你按照某些規(guī)則組合了單詞,并且你選擇了有某些意義的正確的單詞結(jié)束了句子。
Farhana:OK,這意味著什么呢?
Shubho:面向?qū)ο笤瓌t與這類(lèi)似。OOP指的是面向?qū)ο缶幊痰幕驹瓌t和核心思路。在這里,OOP可以比作英語(yǔ)基礎(chǔ)語(yǔ)法,這些語(yǔ)法教你如何用單詞構(gòu)造有意義且正確的句子,OOP教你在代 碼中構(gòu)造類(lèi),并在類(lèi)里封裝屬性和方法,同時(shí)構(gòu)造他們之間的層次關(guān)系。
Farhana:嗯..我有點(diǎn)感覺(jué)了,這里有OOD嗎?
Shubho:馬上就有答案?,F(xiàn)在假定你需要就某些主題寫(xiě)幾篇文章或隨筆。你也希望就幾個(gè)你擅長(zhǎng)主體寫(xiě)幾本書(shū)。對(duì)寫(xiě)好文章/隨筆或書(shū)來(lái)說(shuō),知道如何造句是不夠的,對(duì)嗎?為了使讀者能更輕 ? 松的明白你講的內(nèi)容,你需要寫(xiě)更多的內(nèi)容,學(xué)習(xí)以更好的方式解釋它。
Farhana:看起來(lái)有點(diǎn)意思...繼續(xù)。
Shubho: 現(xiàn)在,如果你想就某個(gè)主題寫(xiě)一本書(shū),如學(xué)習(xí)OOD,你知道如何把一個(gè)主題分為幾個(gè)子主題。你需要為這些題目寫(xiě)幾章內(nèi)容,也需要在這些章節(jié)中寫(xiě)前言,簡(jiǎn)介, 例子和其他段落。 ? 你需要為寫(xiě)個(gè)整體框架,并學(xué)習(xí)一些很好的寫(xiě)作技巧以便讀者能更容易明白你要說(shuō)的內(nèi)容。這就是整體規(guī)劃。
在軟件開(kāi)發(fā)中,OOD是整體思路。在某種程度上,設(shè)計(jì)軟件時(shí),你的類(lèi)和代碼需能達(dá)到模塊化,可復(fù)用,且靈活,這些很不錯(cuò)的指導(dǎo)原則不用你重新發(fā)明創(chuàng)造。確實(shí)有些原則你已經(jīng)在你的類(lèi)和對(duì)象中已經(jīng)用到了,對(duì)嗎?
Farhana:嗯...有個(gè)大概的印象了,但需要繼續(xù)深入。
Shubho:別擔(dān)心,你馬上就會(huì)學(xué)到。我們繼續(xù)討論下去。
為什么要OOD?
Shubho:這是一個(gè)非常重要的問(wèn)題。當(dāng)我們能很快地設(shè)計(jì)一些類(lèi),完成開(kāi)發(fā)并發(fā)布時(shí),為什么我們需要關(guān)心OOD?那樣子還不夠嗎?
Farhana:嗯,我早先并不知道OOD,我一直就是開(kāi)發(fā)并發(fā)布項(xiàng)目。那么關(guān)鍵是什么?
Shubho:好的,我先給你一句名言:
走在結(jié)冰的河邊不會(huì)濕鞋,開(kāi)發(fā)需求不變的項(xiàng)目暢通無(wú)阻(Walking on water and developing software from a specification are easy if both are frozen)
-Edward V.?Berard
Farhana:你的意思是軟件開(kāi)發(fā)說(shuō)明書(shū)會(huì)不斷變化?
Shubho:非常正確!軟件開(kāi)發(fā)唯一的真理是“軟件一定會(huì)變化”。為什么?
因?yàn)槟愕能浖鉀Q的是現(xiàn)實(shí)生活中的業(yè)務(wù)問(wèn)題,而現(xiàn)實(shí)生活中得業(yè)務(wù)流程總是在不停的變化。
假設(shè)你的軟件在今天工作的很好。但它能靈活的支持“變化”嗎?如果不能,那么你就沒(méi)有一個(gè)設(shè)計(jì)敏捷的軟件。
Farhana:好,那么請(qǐng)解釋一下“設(shè)計(jì)敏捷的軟件”。
Shubho:"一個(gè)設(shè)計(jì)敏捷的軟件能輕松應(yīng)對(duì)變化,能被擴(kuò)展,并且能被復(fù)用。"
并且應(yīng)用好"面向?qū)ο笤O(shè)計(jì)"是做到敏捷設(shè)計(jì)的關(guān)鍵。那么,你什么時(shí)候能說(shuō)你在代碼中很好的應(yīng)用了OOD?
Farhana:這正是我的問(wèn)題。
Shubho:如果你代碼能做到以下幾點(diǎn),那么你就正在OOD:
- 面向?qū)ο?/li>
- 復(fù)用
- 能以最小的代價(jià)滿足變化
- 不用改變現(xiàn)有代碼滿足擴(kuò)展
Farhana:還有?
Shubho:我們并不是孤立的。很多人在這個(gè)問(wèn)題上思考了很多,也花費(fèi)了很大努力,他們?cè)噲D做好OOD,并為OOD指出幾條基本的原則(那些靈感你能用之于你的OOD)。他們最終也確實(shí)總結(jié)出了一些通用的設(shè)計(jì)模式(基于基本的原則)。
Farhana:你能說(shuō)幾個(gè)嗎?
Shubho:當(dāng)然。這里有很多涉及原則,但最基本的是叫做SOLID的5原則(感謝Uncle Bob,偉大OOD導(dǎo)師)。
?
S = 單一職責(zé)原則 Single Responsibility Principle O = 開(kāi)放閉合原則 Opened Closed Principle L = Liscov替換原則 Liscov Substitution Principle I = 接口隔離原則 Interface Segregation Principle D = 依賴(lài)倒置原則 Dependency Inversion Principle?
接下去,我們會(huì)仔細(xì)探討每一個(gè)原則。
單一職責(zé)原則
Shubho:我先給你展示一張海報(bào)。我們應(yīng)當(dāng)謝謝做這張海報(bào)的人,它非常有意思。
單一職責(zé)原則海報(bào)
它說(shuō):"并不是因?yàn)槟隳?#xff0c;你就應(yīng)該做"。為什么?因?yàn)殚L(zhǎng)遠(yuǎn)來(lái)看它會(huì)帶來(lái)很多管理問(wèn)題。
從面向?qū)ο蠼嵌冉忉尀?#xff1a;"引起類(lèi)變化的因素永遠(yuǎn)不要多于一個(gè)。"
或者說(shuō)"一個(gè)類(lèi)有且只有一個(gè)職責(zé)"。
Farhana:能解釋一下嗎?
Shubho:當(dāng)然,這個(gè)原則是說(shuō),如果你的類(lèi)有多于一個(gè)原因會(huì)導(dǎo)致它變化(或者多于一個(gè)職責(zé)),你需要一句它們的職責(zé)把這個(gè)類(lèi)拆分為多個(gè)類(lèi)。
Farhana:嗯...這是不是意味著在一個(gè)類(lèi)里不能有多個(gè)方法?
Shubho:不。你當(dāng)然可以在一個(gè)類(lèi)中包含多個(gè)方法。問(wèn)題是,他們都是為了一個(gè)目的。如今為什么拆分是重要的?
那是因?yàn)?#xff1a;
- 每個(gè)職責(zé)是軸向變化的;
- 如果類(lèi)包含多個(gè)職責(zé),代碼會(huì)變得耦合;
Farhana:能給我一個(gè)例子嗎?
Shubho:當(dāng)然,看一下下面的類(lèi)層次。當(dāng)然這個(gè)例子是從Uncle Bob那里得來(lái),再謝謝他。
違反單一職責(zé)原則的類(lèi)結(jié)構(gòu)圖
這里,Rectangle類(lèi)做了下面兩件事:
- 計(jì)算矩形面積;
- 在界面上繪制矩形;
并且,有兩個(gè)應(yīng)用使用了Rectangle類(lèi):
- 計(jì)算幾何應(yīng)用程序用這個(gè)類(lèi)計(jì)算面積;
- 圖形程序用這個(gè)類(lèi)在界面上繪制矩形;
這違反了SRP(單一職責(zé)原則);
Farhana:如何違反的?
Shubho:你看,Rectangle類(lèi)做了兩件事。在一個(gè)方法里它計(jì)算了面積,在另外一個(gè)方法了它返回一個(gè)表示矩形的GUI。這會(huì)帶來(lái)一些有趣的問(wèn)題:
在計(jì)算幾何應(yīng)用程序中我們必須包含GUI。也就是在開(kāi)發(fā)幾何應(yīng)用時(shí),我們必須引用GUI庫(kù);
圖形應(yīng)用中Rectangle類(lèi)的變化可能導(dǎo)致計(jì)算幾何應(yīng)用變化,編譯和測(cè)試,反之亦然;
Farhana:有點(diǎn)意思。那么我猜我們應(yīng)該依據(jù)職責(zé)拆分這個(gè)類(lèi),對(duì)嗎?
Shubho:非常對(duì),你猜我們應(yīng)該做些什么?
Farhana:當(dāng)然,我試試。下面是我們可能要做的:
拆分職責(zé)到兩個(gè)不同的類(lèi)中,如:
- Rectangle:這個(gè)類(lèi)應(yīng)該定義Area()方法;
- RectangleUI:這個(gè)類(lèi)應(yīng)繼承Rectangle類(lèi),并定義Draw()方法。
Shubho:非常好。在這里,Rectangle類(lèi)被計(jì)算幾何應(yīng)用使用,而RectangleUI被圖形應(yīng)用使用。我們甚至可以分離這些類(lèi)到兩個(gè)獨(dú)立的DLL中,那會(huì)允許我們?cè)谧兓瘯r(shí)不需要關(guān)心另一個(gè)就可以實(shí)現(xiàn)它。
Farhana:謝謝,我想我明白SRP了。SRP看起來(lái)是把事物分離成分子部分,以便于能被復(fù)用和集中管理。我們也不能把SRP用到方法級(jí)別嗎?我的意思是,我們可以寫(xiě)一些方法,它們包含做很多事的代碼。這些方法可能違反SRP,對(duì)嗎?
Shubho:你理解了。你應(yīng)當(dāng)分解你的方法,讓每個(gè)方法只做某一項(xiàng)工作。那樣允許你復(fù)用方法,并且一旦出現(xiàn)變化,你能購(gòu)以修改最少的代碼滿足變化。
開(kāi)放閉合原則
Shubho:這里是開(kāi)放閉合原則的海報(bào)
開(kāi)放閉合原則海報(bào)
從面向?qū)ο笤O(shè)計(jì)角度看,它可以這么說(shuō):"軟件實(shí)體(類(lèi),模塊,函數(shù)等等)應(yīng)當(dāng)對(duì)擴(kuò)展開(kāi)放,對(duì)修改閉合。"
通俗來(lái)講,它意味著你應(yīng)當(dāng)能在不修改類(lèi)的前提下擴(kuò)展一個(gè)類(lèi)的行為。就好像我不需要改變我的身體而可以穿上衣服。
Farhana:有趣。你能夠按照你意愿穿上不同的衣服來(lái)改變面貌,而從不用改造身體。你對(duì)擴(kuò)展開(kāi)放了,對(duì)不?
Shubho:是的。在OOD里,對(duì)擴(kuò)展開(kāi)發(fā)意味著類(lèi)或模塊的行為能夠改變,在需求變化時(shí)我們能以新的,不同的方式讓模塊改變,或者在新的應(yīng)用中滿足需求。
Farhana:并且你的身體對(duì)修改是閉合的。我喜歡這個(gè)例子。當(dāng)需要變化時(shí),核心類(lèi)或模塊的源代碼不應(yīng)當(dāng)改動(dòng)。你能用些例子解釋一下嗎?
Shubho:當(dāng)然,看下面這個(gè)例子。它不支持"開(kāi)放閉合"原則。
違反開(kāi)發(fā)閉合原則的類(lèi)結(jié)構(gòu)
你看,客戶端和服務(wù)段都耦合在一起。那么,只要出現(xiàn)任何變化,服務(wù)端變化了,客戶端一樣需要改變。
Farhana:理解。如果一個(gè)瀏覽器以緊耦合的方式按照指定的服務(wù)器(比如IIS)實(shí)現(xiàn),那么如果服務(wù)器因?yàn)槟承┰虮黄渌?wù)器(如Apache)替換了,那么瀏覽器也需要修改或替換。這確實(shí)很可怕!
Shubho:對(duì)的。下面是正確的設(shè)計(jì)。
遵循開(kāi)放閉合原則的類(lèi)結(jié)構(gòu)
在這個(gè)例子中,添加了一個(gè)抽象的服務(wù)器類(lèi),客戶端包含一個(gè)抽象類(lèi)的引用,具體的服務(wù)類(lèi)實(shí)現(xiàn)了抽象服務(wù)類(lèi)。那么,因任何原因引起服務(wù)實(shí)現(xiàn)發(fā)生變化時(shí),客戶端都不需要任何改變。
這里抽象服務(wù)類(lèi)對(duì)修改是閉合的,實(shí)體類(lèi)的實(shí)現(xiàn)對(duì)擴(kuò)展是開(kāi)放的。
Farhana:我明白了,抽象是關(guān)鍵,對(duì)嗎?
Shubho:是的,基本上,你抽象的東西是你系統(tǒng)的核心內(nèi)容,如果你抽象的好,很可能在擴(kuò)展功能時(shí)它不需要任 何修改(就像服務(wù)是一個(gè)抽象概念)。如果在實(shí)現(xiàn)里定義了抽象的東西(比如IIS服務(wù)器實(shí)現(xiàn)的服務(wù)),代碼要盡可能以抽象(服務(wù))為依據(jù)。這會(huì)允許你擴(kuò)展抽 象事物,定義一個(gè)新的實(shí)現(xiàn)(如Apache服務(wù)器)而不需要修改任何客戶端代碼。
Liskov's 替換原則
Shubho:"Liskov's替換原則(LSP)"聽(tīng)起來(lái)很難,卻是很有用的基本概念。看下這幅有趣的海報(bào):
Liskov替換原則海報(bào)
這個(gè)原則意思是:"子類(lèi)型必須能夠替換它們基類(lèi)型。"
或者換個(gè)說(shuō)法:"使用基類(lèi)引用的函數(shù)必須能使用繼承類(lèi)的對(duì)象而不必知道它。"
Farhana:不好意思,聽(tīng)起來(lái)有點(diǎn)困惑。我認(rèn)為這個(gè)OOP的基本原則之一。也就是多態(tài),對(duì)嗎?為什么一個(gè)面向?qū)ο笤瓌t需要這么說(shuō)呢?
Shubho:問(wèn)的好。這就是你的答案:
在基本的面向?qū)ο笤瓌t里,"繼承"通常是"is a"的關(guān)系。如果"Developer" 是一個(gè)"SoftwareProfessional",那么"Developer"類(lèi)應(yīng)當(dāng)繼承"SoftwareProfessional"類(lèi)。在類(lèi)設(shè)計(jì)中"Is a"關(guān)系非常重要,但它容易沖昏頭腦,結(jié)果使用錯(cuò)誤的繼承造成錯(cuò)誤設(shè)計(jì)。
"Liskov替換原則"正是保證繼承能夠被正確使用的方法。
Farhana:我明白了。有意思。
Shubho:是的,親愛(ài)的,確實(shí)。我們看個(gè)例子:
Liskov替換原則類(lèi)結(jié)構(gòu)圖
這里,KingFisher類(lèi)擴(kuò)展了Bird基類(lèi),并繼承了Fly()方法,這看起來(lái)沒(méi)問(wèn)題。
現(xiàn)在看下面的例子:
違反Liskov替換原則類(lèi)結(jié)構(gòu)圖
Ostrich(鴕鳥(niǎo))是一種鳥(niǎo)(顯然是),并從Bird類(lèi)繼承。它能飛嗎?不能,這個(gè)設(shè)計(jì)就違反了LSP。
所以,即使在現(xiàn)實(shí)中看起來(lái)沒(méi)問(wèn)題,在類(lèi)設(shè)計(jì)中,Ostrich不應(yīng)該從Bird類(lèi)繼承,這里應(yīng)該從Bird中分離一個(gè)不會(huì)飛的類(lèi),Ostrich應(yīng)該繼承與它。
Farhana:好,明白了。那么讓我來(lái)試著指出為什么LSP這么重要:
- 如果沒(méi)有LSP,類(lèi)繼承就會(huì)混亂;如果子類(lèi)作為一個(gè)參數(shù)傳遞給方法,將會(huì)出現(xiàn)未知行為;
- 如果沒(méi)有LSP,適用與基類(lèi)的單元測(cè)試將不能成功用于測(cè)試子類(lèi);
對(duì)嗎?
Shubho:非常正確。你能設(shè)計(jì)對(duì)象,使用LSP做為一個(gè)檢查工作來(lái)測(cè)試?yán)^承是否正確。
接口分離原則
Shubho:今天我們學(xué)習(xí)"接口分離原則",這是海報(bào):
接口分離原則海報(bào)
Farhana:這是什么意思?
Shubho:它的意思是:"客戶端不應(yīng)該被迫依賴(lài)于它們不用的接口。"
Farhana:請(qǐng)解釋一下。
Shubho:當(dāng)然,這是解釋:
假設(shè)你想買(mǎi)個(gè)電視機(jī),你有兩個(gè)選擇。一個(gè)有很多開(kāi)關(guān)和按鈕,它們看起來(lái)很混亂,且好像對(duì)你來(lái)說(shuō)沒(méi)必要。另一個(gè)只有幾個(gè)開(kāi)關(guān)和按鈕,它們很友好,且適合你使用。假定兩個(gè)電視機(jī)提供同樣的功能,你會(huì)選哪一個(gè)?
Farhana:當(dāng)然是只有幾個(gè)開(kāi)關(guān)和按鈕的第二個(gè)。
Shubho:對(duì),但為什么?
Farhana:因?yàn)槲也恍枰切┛雌饋?lái)混亂又對(duì)我沒(méi)用的開(kāi)關(guān)和按鈕。
?
Shubho:以便外部能夠知道這些類(lèi)有哪些可用的功能,客戶端代碼也能根據(jù)接口來(lái)設(shè)計(jì).現(xiàn)在,如果接口太大,包含很多暴露的方法,在外界看來(lái)會(huì)很混亂.接口包含太多的方法也使其可用性降低,像這種包含了無(wú)用方法的"胖接口"會(huì)增加類(lèi)之間的耦合.你通過(guò)接口暴露類(lèi)的功能,對(duì).同樣地,假設(shè)你有一些類(lèi),
這也引起了其他問(wèn)題.如果一個(gè)類(lèi)想實(shí)現(xiàn)該接口,那么它需要實(shí)現(xiàn)所有的方法,盡管有些對(duì)它來(lái)說(shuō)可能完全沒(méi)用.所以說(shuō)這么做會(huì)在系統(tǒng)中引入不必要的復(fù)雜度,降低可維護(hù)性或魯棒性.
接口隔離原則確保實(shí)現(xiàn)的接口有他們共同的職責(zé),它們是明確的,易理解的,可復(fù)用的.
Farhana:你的意思是接口應(yīng)該僅包含必要的方法,而不該包含其它的.我明白了.Shubho:非常正確.一起看個(gè)例子.
下面是違反接口隔離原則的一個(gè)胖接口 ? ?注意到IBird接口包含很多鳥(niǎo)類(lèi)的行為,包括Fly()行為.現(xiàn)在如果一個(gè)Bird類(lèi)(如Ostrich)實(shí)現(xiàn)了這個(gè)接口,那么它需要實(shí)現(xiàn)不必要的Fly()行為(Ostrich不會(huì)飛).
Farhana:確實(shí)如此。那么這個(gè)接口必須拆分了?
Shubho:是的。這個(gè)"胖接口"應(yīng)該拆分未兩個(gè)不同的接口,IBird和IFlyingBird,IFlyingBird繼承自IBird.
? ?這里如果一種鳥(niǎo)不會(huì)飛(如Ostrich),那它實(shí)現(xiàn)IBird接口。如果一種鳥(niǎo)會(huì)飛(如KingFisher),那么它實(shí)現(xiàn)IFlyingBird.
Farhana:所以回頭看包含了很多開(kāi)關(guān)和按鈕的電視機(jī)的例子,電視機(jī)制造商應(yīng)該有一個(gè)電視機(jī)的圖紙,開(kāi)關(guān)和按鈕都在這個(gè)方案里。不論任何時(shí)候,當(dāng)他們向制造一種新款電視機(jī)時(shí),如果他們想復(fù)用這個(gè)圖紙,他們將需要在這個(gè)方案里添加更多的開(kāi)關(guān)和按鈕。那么他們將沒(méi)法復(fù)用這個(gè)方案,對(duì)嗎?
Shubho:對(duì)的。
Farhana:如果他們確實(shí)需要復(fù)用方案,它們應(yīng)當(dāng)把電視機(jī)的圖紙份為更小部分,以便在任何需要造新款電視機(jī)的時(shí)候復(fù)用這點(diǎn)小部分。
Shubho:你理解了。
依賴(lài)倒置原則
Shubho:這是SOLID原則里最后一個(gè)原則。這是海報(bào)
? ?它的意思是:高層模塊不應(yīng)該依賴(lài)底層模塊,兩者都應(yīng)該依賴(lài)其抽象
Shubho:考慮一個(gè)現(xiàn)實(shí)中的例子。你的汽車(chē)是由很多如引擎,車(chē)輪,空調(diào)和其它等部件組成,對(duì)嗎?
Farhana:是的
Shubho:好,它們沒(méi)有一個(gè)是嚴(yán)格的構(gòu)建在一個(gè)單一單元里;換句話說(shuō),它們都是可插拔的,因此當(dāng)引擎或車(chē)輪出問(wèn)題時(shí),你可以修理它(而不需要修理其它部件),甚至可以換一個(gè)。
在替換時(shí),你僅需要確保引擎或車(chē)輪符合汽車(chē)的設(shè)計(jì)(如汽車(chē)能使用任何1500CC的引擎或任何18寸的車(chē)輪)。
當(dāng)然,汽車(chē)也可能允許你在1500CC引擎的地方安裝一個(gè)2000CC的引擎,事實(shí)上對(duì)某些制造商(如豐田汽車(chē))是一樣的。
現(xiàn)在,如果你的汽車(chē)的零部件不具備可插拔性會(huì)有什么不同?
Farhana:那會(huì)很可怕!因?yàn)槿绻?chē)的引擎出故障了,你可能修理整部車(chē)或者需要買(mǎi)一個(gè)新的。
Shubho:是的,那么該如何做到"可插拔性"呢?
Farhana:這里抽象是關(guān)鍵,對(duì)嗎?
Shubho:是的,在現(xiàn)實(shí)中,汽車(chē)是高級(jí)模塊或?qū)嶓w,它依賴(lài)于低級(jí)模塊或?qū)嶓w,如引擎或車(chē)輪。
相比直接依賴(lài)于引擎或車(chē)輪,汽車(chē)應(yīng)依賴(lài)于某些抽象的有規(guī)格的引擎或車(chē)輪,以便于如果任何引擎或車(chē)輪符合抽象,那么它們都能組合到汽車(chē)中,汽車(chē)也能跑動(dòng)。
一起看下面的類(lèi)圖
? ?Shubho:注意到上面Car類(lèi)有兩個(gè)屬性,它們都是抽象類(lèi)型(接口)。引擎和車(chē)輪是可插拔的,因?yàn)槠?chē)能接受任何實(shí)現(xiàn)了聲明接口的對(duì)象,并且Car類(lèi)不需要做任何改動(dòng)。
Farhana:所以,如果代碼中不用依賴(lài)倒置,我們將面臨如下風(fēng)險(xiǎn):
-
使用低級(jí)類(lèi)會(huì)破環(huán)高級(jí)代碼;
-
當(dāng)?shù)图?jí)類(lèi)變化時(shí)需要很多時(shí)間和代價(jià)來(lái)修改高級(jí)代碼;
-
產(chǎn)生低復(fù)用的代碼;
Shubho:你完全掌握了,親愛(ài)的!
?總結(jié)Shubho:除SOLID原則外還有很多其它的面向?qū)ο笤瓌t。如:
"組合替代繼承":這是說(shuō)相對(duì)于繼承,要更傾向于使用組合;
"笛米特法則":這是說(shuō)"你的類(lèi)對(duì)其它類(lèi)知道的越少越好";
"共同封閉原則":這是說(shuō)"相關(guān)類(lèi)應(yīng)該打包在一起";
"穩(wěn)定抽象原則":這是說(shuō)"類(lèi)越穩(wěn)定,越應(yīng)該由抽象類(lèi)組成";
Farhana:我應(yīng)該學(xué)習(xí)那些原則嗎?
Shubho:當(dāng)然可以。你可以從整個(gè)網(wǎng)上學(xué)習(xí)。僅僅需要Google一下那些原則,然后嘗試?yán)斫馑?。?dāng)然如果有需要,盡管問(wèn)我。
Farhana:在那些設(shè)計(jì)原則之上我聽(tīng)說(shuō)過(guò)很多設(shè)計(jì)模式。
Shubho:對(duì)的。設(shè)計(jì)模式只是對(duì)一些經(jīng)常出現(xiàn)的場(chǎng)景的一些通用設(shè)計(jì)建議。這些靈感主要來(lái)自于面向?qū)ο笤瓌t。你可以把設(shè)計(jì)模式看作"框架",把OOD原則看作"規(guī)范".
Farhana:那么接下去我將學(xué)習(xí)設(shè)計(jì)模式嗎?
Shubho:是的,親愛(ài)的。
Farhana:那會(huì)很有意思,對(duì)嗎?
Shubho:是,那確實(shí)令人興奮。
轉(zhuǎn)載于:https://www.cnblogs.com/xyqCreator/archive/2012/10/23/2735234.html
總結(jié)
以上是生活随笔為你收集整理的如何向妻子解释OOD(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 驾照一般多少钱啊?
- 下一篇: WinForm Paenl里面添加For