




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、精品文檔關(guān)于軟件的設(shè)計(jì)原那么有很多,對于設(shè)計(jì)原那么的掌握、理解、實(shí)踐及升華是架構(gòu)師的一項(xiàng)極為 之必要的修煉.記得在12年前第一次閱讀?敏捷開發(fā)?時,五大根本設(shè)計(jì)原那么就深深地植入到我的腦海中一直影響至今,我也由此獲益良多. 設(shè)計(jì)原那么當(dāng)然不止只有五種,最主要的面向?qū)ο蟮脑O(shè)計(jì)原那么有以下這些:單一責(zé)任原那么SRP-就一個類而言,應(yīng)該僅有一個引起它變化的原因開-閉原那么 OCP-軟件實(shí)體類,模塊,函數(shù)等應(yīng)該是可以擴(kuò)展的,但是不 可以修改里氏替換原那么LSP«依賴倒置原那么DIP子類必須能夠替換它們的基類型 抽象不應(yīng)該依賴于細(xì)節(jié).細(xì)節(jié)應(yīng)該依賴于抽象.4接口隔離原那么ISP-不應(yīng)該強(qiáng)迫客戶依
2、賴于它們不用的方法.接口屬于客戶,不屬于它所在的類層次結(jié)構(gòu).重用發(fā)布等階原那么REP-重用的粒度就是發(fā)布的粒度.共同封閉原那么 CCP-包中的所有類對于同一類性質(zhì)的變化應(yīng)該是共同封閉的. 一個變化假設(shè)對一個包產(chǎn)生影響,那么將對該包中的所有類產(chǎn)生影響,而對于其他的 包不造成影響.共同重用原那么CRP- 一個包中所有類應(yīng)該是共同理用的.如果重用了包中的一 個類,那么就要重用包中的所有類.無環(huán)依賴原那么ADP-在包的依賴關(guān)系圖中不允許存在環(huán).穩(wěn)定依賴原那么 SDP-朝著穩(wěn)定的方向進(jìn)行依賴.穩(wěn)定抽象原那么SAP-包的抽象程度應(yīng)該和其穩(wěn)定程度一致.合成/聚合復(fù)用原那么CARP-要盡量使用合成/聚合,盡量
3、不要使用繼承當(dāng)然面向?qū)ο蟮脑O(shè)計(jì)原那么遠(yuǎn)遠(yuǎn)不止這些,設(shè)計(jì)原那么是伴隨著開發(fā)語言的開展應(yīng)用和軟件開發(fā)經(jīng)驗(yàn)的累加總結(jié)得出的經(jīng)驗(yàn)匯總,隨著語言的演變、開發(fā)方法的進(jìn)步還會不斷地衍生和進(jìn)化出更多的的設(shè)計(jì)原那么. 應(yīng)用設(shè)計(jì)原那么可以避開很多的設(shè)計(jì)中的陷阱與誤區(qū),但在應(yīng)用設(shè)計(jì)原那么的同時需要緊記一點(diǎn):設(shè)計(jì)原那么本質(zhì)上是一些經(jīng)驗(yàn)條框,是設(shè)計(jì)的導(dǎo)盲杖而不要讓它們成為束縛設(shè)計(jì)思想的牢籠.每個架構(gòu)師在經(jīng)歷長期的實(shí)踐后也會慢慢建立屬于自己的設(shè)計(jì)原那么.多年來我也總結(jié)出了一些設(shè)計(jì)原那么,并將上面這些這種可用于代碼設(shè)計(jì)的原那么歸納為:代碼設(shè)計(jì)原那么,另外一些應(yīng)用于意識與設(shè)計(jì)過程中的原那么稱為意識-行為原那么.以下我將會分別
4、講述我對這些設(shè)計(jì)原那么的理解與運(yùn)用的經(jīng)驗(yàn).意識-行為原那么意識決定行為,很多的設(shè)計(jì)失誤并不單純源自于對設(shè)計(jì)原那么的把握缺乏,而更多可能源自于架構(gòu)師在意識指導(dǎo)上的錯誤,所以在開始設(shè)計(jì)之前應(yīng)該先建立正確的思想與意識引導(dǎo).以下的這些意識-行為原那么是我從很屢次的跌倒中總結(jié)出的一些心得,將期作為原那么是為了 時刻引導(dǎo)自己不會在類似問題中犯錯.堅(jiān)持創(chuàng)新原那么首先談?wù)勀0迨皆O(shè)計(jì),我相信模板對于每一位開發(fā)人員和設(shè)計(jì)人員來說都是非常好的東 西,由于它可以 快速構(gòu)建出 成熟的代碼、結(jié)構(gòu)或 UI.拿來主義在業(yè)界盛極不衰,對 于架構(gòu)師而言模板也有這種成效,在設(shè)計(jì)的過程中我們會經(jīng)常遇到很多必須而不重要的雞肋模塊,沒有
5、它們系統(tǒng)會變得不完整,而它們的存在并不能為系統(tǒng)增加任何的特色功能如:用戶治理、角色治理或系統(tǒng)設(shè)置等. 常見做法是,直接采用第三方模塊或是從已有的其 它工程中復(fù)用類似的模塊,你是這樣的嗎?至少我是經(jīng)常這樣做的,由于我們的中國式項(xiàng)目通常是 驗(yàn)收驅(qū)動,能通過驗(yàn)收、成熟可用就好.如果整個工程都只是由各類模板化的模 塊所構(gòu)成,那么這個工程其實(shí)不需要架構(gòu)師,由于不存在任何設(shè)計(jì), 所有的工作只是一種 融合Fusion .可能這樣說會有很多人會吐槽說這是一種資源整合水平,從 趕工程的角度來說這無可口非, 但從技術(shù)含量與本質(zhì)上說確實(shí)不存在任何設(shè)計(jì)成分,這類拼裝性或是復(fù)制性的工程只需要工程經(jīng)理配備幾個高級程序員就
6、能完成了.我曾在表達(dá)思維與駕馭方法論一文中提到與銷售的溝通方法,其中就有一條:至少說出系統(tǒng)的三個特色這個表述對銷售具有市場意義以外,其實(shí)對于架構(gòu)師是起到一個重要的提醒作用同時也是在建立一種設(shè)計(jì)原那么:架構(gòu)設(shè)計(jì)中模板的拼裝是不可預(yù)防的,重要的是必須參加屬于你的特色設(shè)計(jì)很難有人記得住整個軟件的設(shè)計(jì)師,而卻很容易記住某項(xiàng)極具特色功能的設(shè)計(jì)者.特色是架構(gòu)師在軟件中所留下的一種重要的印記,也是在團(tuán)隊(duì)中配備架構(gòu)師的意義所在.設(shè)計(jì)出完全可被模板化重用的設(shè)計(jì)是一功力,而當(dāng)中小型企業(yè)內(nèi)出現(xiàn)這樣的設(shè)計(jì)之日就是架構(gòu)師離開企業(yè)之時,或許這也是當(dāng)下中國架構(gòu)師之殤.保持特色保住飯碗,你懂的.固守本質(zhì)原那么唯一不變的就是變
7、化本身 一Jerry Marktos ?人月神話?不變只是愿望,變化才是永恒 一Swift看到這兩句經(jīng)典是不是猜到我想就變化二字來一次老生常談 ?其實(shí)不然,這兩個字在業(yè)內(nèi)估計(jì)也討論了 20多年了,也說爛了.我之所以引用這兩位大師的名言只是想無時無刻提 醒自己要了解身邊的每一個變化,對他們的源頭產(chǎn)生興趣,從而深入了解.世界上不會有無緣無故的愛,也沒有無緣無故的恨一切皆有根源,那是本質(zhì).我們來將 本質(zhì)與 變化這兩個哲學(xué)性的問題應(yīng)用到軟件開發(fā)的范疇內(nèi)來看一個軟件產(chǎn)品的迭代:用戶的需求在變-他們需要增加更多的功能,最求更高質(zhì)量的用戶體驗(yàn).代碼在變-不斷的重構(gòu)、測試,持續(xù)集成,讓代碼變得容讀,穩(wěn)定.老板
8、的想法在變 -由于市場需求在變,需要為軟件參加更多的特色滿足市場.架構(gòu)在變-采用更新式的技術(shù)體系,獲得更高效的生產(chǎn)力,更為穩(wěn)定、平安的運(yùn)行環(huán)境.而唯一不變的是: 軟件的核心.正如:Windows 變了 N個版本最后還是操作平臺,Ofice衍生了多代后假設(shè)然在處理文檔文件.變化是表像,不穩(wěn)定且可定制的;本質(zhì)是核心,必須穩(wěn)定,可擴(kuò)展而不可修改;被固定 的變化那么可納入核心.架構(gòu)應(yīng)從本質(zhì)入手,一切復(fù)雜的事物都應(yīng)可被分解為簡單的原理和構(gòu)成,本質(zhì)之外的內(nèi)容皆可變化.我們來舉例說明,設(shè)計(jì)一個電子商務(wù)網(wǎng)站,其核心就可被分解為購物車與訂單狀態(tài)跟蹤這是不可變的除非群眾的整體購物行為發(fā)生了本質(zhì)上的改變,為了增加用
9、戶體驗(yàn)我們選用美觀舒適的界面套件如Bootstrap ,如果進(jìn)一步提升用戶體驗(yàn)?zāi)敲纯梢圆捎肧PA的架構(gòu)讓客戶在 Web上獲得Native式的使用體驗(yàn);為了讓用戶使用不同的支付方式, 我們就需要定義支付網(wǎng)關(guān)接口引入變化支持已有的支付平臺,也為將來 可能出現(xiàn)的支付平臺留有擴(kuò)展.為了增強(qiáng)網(wǎng)站對用戶的粘性,我們就需要增加社區(qū)模塊,并采用云存儲或是其它的BigData技術(shù)以支撐大數(shù)據(jù)量的運(yùn)轉(zhuǎn);.最后,一切的本質(zhì)仍然不變,電商網(wǎng) 站,變的是擴(kuò)展性、易用性、伸縮性等等.架構(gòu)師可以向其中添加的功能太多太多,但必須 固守本質(zhì)才能讓整個產(chǎn)品不會成為一個由高技術(shù)打造出來的怪物,在增加新功能時參考代碼商人原那么的指引
10、.'代碼商人原那么永遠(yuǎn)不要投資未來,絕不設(shè)計(jì)沒有回報的功能不知道你是否擁有類似的經(jīng)歷:在與客戶的交流中,你的老板和經(jīng)理在不斷地向客戶描繪未來圖景,而在其中包含了很多幾乎是客戶沒有需要的特色?在你設(shè)計(jì)整體架構(gòu)時,有一種沖動讓你很想將某項(xiàng)由靈感觸發(fā)對于系統(tǒng)將來的擴(kuò)展需要很有用的功能或模塊參加其中呢?在你的代碼里面有多少個方法或類是可以被刪除,但你認(rèn)為他們可以用于以后擴(kuò)展而手下留碼的呢?你是否曾與經(jīng)理或工程組長為了是否增加某個很有可能成為特色且被你實(shí)現(xiàn)出來的 功能爭論不休呢?衡量標(biāo)準(zhǔn)的尺子掌握在架構(gòu)師手中,如果設(shè)計(jì)中出現(xiàn)林林總總的這些未來功能您會如何來對待呢?是直接砍掉還是將其包裝成為特色呢
11、?此時架構(gòu)師不單單是需要作為一名技術(shù)人員的角度考慮這個功能是否在將來可用,而更多的是需要考慮 本錢.每個功能甚至每行代碼都需要付出 人-月本錢,一旦本錢失控,軟件就會化身人狼吞掉你的工程,而最后也只能懊悔沒有找到銀彈.每個 未來功能如何不能對現(xiàn)有工程帶來即時性的回報,必須砍掉!即使這個功能有如何的美妙、高深或是在將來具有非凡的意義,還是將它放入研 究室成為其它工程的技術(shù)儲藏吧.站在商人的立場:每一分錢的本錢投入,都需要有足夠 的利益回報.未來永遠(yuǎn)是美好的、 飽滿的同時也是浮云, 而現(xiàn)實(shí)卻往往是充滿骨感. 在架構(gòu)或代碼中 透支未來極少數(shù)可獲得回報, 由于這些 投資都具有不可預(yù)見性只是一些嘗試,
12、在產(chǎn)品中除 了市場策略需要外的這類過分投資就得有陷入 維護(hù)未來的心理覺悟.新的功能、未來的特色更應(yīng)該收集起來,作為一下版本中可選項(xiàng),通過詳細(xì)的市場研究再考慮參加到產(chǎn)品中. 當(dāng)然,對于大型軟件企業(yè)這個原那么根本上是多余的,由于很多成熟的軟件企業(yè)對需求的限制極其嚴(yán)格與標(biāo)準(zhǔn).但如果你所在的企業(yè)還沒有這樣的治理意識,或具有超脫性的設(shè)計(jì)自由, 那么這條原那么是非常重要的,我們是用代碼換錢的人,更少的代碼換更多的錢才是我們最基 本的生存需要.重構(gòu)優(yōu)先原那么在沒有代碼的時候就應(yīng)該重構(gòu),重構(gòu)是寫出優(yōu)雅代碼的方法而不單純是修改代碼的理論.駱駝與帳篷的故事在風(fēng)沙彌漫的大沙漠,駱駝在四處尋找溫暖的家.后來它終于找到
13、一頂帳篷,可是,帳 篷是別人的也許你的處境跟它一樣!最初,駱駝哀求說,主人,我的頭都凍僵了,讓我把頭伸進(jìn)來緩和暖和吧!主人可憐它, 容許了.過了一陣子,駱駝又說,主人,我的肩膀都凍麻了,讓我再進(jìn)來一點(diǎn)吧!主人可憐 它,又容許了.接著,駱駝不斷的提出要求,想把整個身體都放進(jìn)來.主人有點(diǎn)猶豫,一方面,他害怕駱駝粗大的鼻孔;另一方面,外面的風(fēng)沙那么大,他好 像也需要這樣一位伙伴, 和他共同抵御風(fēng)寒和危險.于是,他有些無奈地背轉(zhuǎn)身去,給駱駝 騰出更多的位子.等到駱駝完全精神并可以掌握帳篷的限制權(quán)的時候,它很不耐煩地說,主人,這頂帳篷是如此狹小以致連我轉(zhuǎn)身都很困難,你就給我出去吧這是一個很有寓意故事,
14、如果將其比喻為開發(fā)過程也很有意思.對于發(fā)臭甚至腐爛代碼我們會馬上說 重構(gòu),但重構(gòu)是否能解決一切問題?你是否試過重構(gòu)失敗呢?重構(gòu)在什么情況下是不可用的呢?如果這些問題在你心中是沒有準(zhǔn)確答案的話,我建議可以重新去閱讀一次?代碼重構(gòu)?一書.我認(rèn)為重構(gòu)不單純是一種開發(fā)期與代碼回憶期所使用的方法, 而是一種設(shè)計(jì)與編碼的思想指導(dǎo)!在設(shè)計(jì)期就應(yīng)運(yùn)用重構(gòu)中的原那么,那是否就可以防腐呢?答案顯然是確定的.重構(gòu)的往往不單純是代碼,而是開發(fā)人員、設(shè)計(jì)人員的思想,不 執(zhí)行甚至沒有代碼標(biāo)準(zhǔn)、隨意命名、隨意復(fù)制/粘貼、隨意調(diào)用這些都必須被杜絕.我并不是指在設(shè)計(jì)重構(gòu)就不需要重構(gòu), 只是這樣做的意義可以大量減少由于發(fā)現(xiàn)臭代碼
15、而去重構(gòu)的本錢.這也可以說是一個團(tuán)隊(duì)性的開發(fā)原那么,在工程之始就得有統(tǒng)一的編碼標(biāo)準(zhǔn)直接使用官方標(biāo)準(zhǔn),并將重構(gòu)中的根本代碼重構(gòu)方法也納入標(biāo)準(zhǔn)中,在開發(fā)過程中強(qiáng)制執(zhí)行標(biāo)準(zhǔn),對 任何可能 腐化的代碼絕對的 零容忍,痛苦只是一時,但好處卻是長久的.代碼設(shè)計(jì)原那么開放-封閉原那么開放圭寸閉原那么又稱 開-閉原那么 Open-Closed Principle (OCP)軟件實(shí)體(如類,模塊,函數(shù)等)應(yīng)該是可以擴(kuò)展的,但是不可以修改.OCP是一個極為之知名的設(shè)計(jì)原那么,簡單的一句話就概括了可時該開放可時該封閉這句話看起來很簡單,一看似乎也會覺得自己領(lǐng)悟了什么,仔細(xì)咀嚼卻覺得內(nèi)中深意無限, 到底應(yīng)怎樣理解這句
16、話且將其應(yīng)用于設(shè)計(jì)中呢?我參考了不少國內(nèi)的資料對此原那么的總結(jié),感覺就是霧里看花,沒有方法找到最為貼切的解釋.我想分幾個方面來詮釋這個原那么:從類設(shè)計(jì)的角度在類設(shè)計(jì)的應(yīng)用中開-閉原那么是一種對類的多態(tài)限制原那么.開閉原那么在基類或超類的設(shè)計(jì)中由為重要,可以簡單地理為對 成員對象的作用域 和 可 重載成員 的限制指引原那么.按 里氏替換原那么基類成員通常對于子類都應(yīng)該可見,也就是說基類成員的作用域的最小作用范圍應(yīng)該是protect ,如果出現(xiàn)大量的 private 成員時就應(yīng)該考慮將 private 成員們別離成其它的類,由于些成員都不適用于其子代而違反了替換原那么而更適用 合成/聚合原那么.在
17、運(yùn)用virtual關(guān)鍵字時需甚重考慮,除了針對某些特殊的設(shè)計(jì)模式如裝飾模式需要大量virtual的支持以外,在沒有必要的情況下盡量預(yù)防.定義可重寫的成員為子類預(yù) 留了改變行為 的余地,但同時也是為子類違反替換原那么 埋下了地雷.當(dāng)子類中出現(xiàn)大量 重寫成員的時候就得考慮該子類是否還應(yīng)該繼承于此類族,由于子類在大量地違反替換原那么 時就意味著它滿足了被別離出類族的條件.同理,在C#內(nèi)一但需要在子類內(nèi)部實(shí)現(xiàn)基類接口時也需要作出同樣的考慮.注:里氏替換原那么是開-閉原那么的一種重要補(bǔ)充,在類設(shè)計(jì)中一般是同時使用從模塊設(shè)計(jì)的角度模塊設(shè)計(jì)的 開-閉原那么是側(cè)重于對接口的限制.而這個在整個架構(gòu)中也尤為重要,
18、因 為模塊間的 開-閉是直接影響系統(tǒng)級的耦合度.模塊間的開閉需要衡量本錢并不是將所有的細(xì)節(jié)都開放使用模塊具有極強(qiáng)的可擴(kuò)展性就會有很高的重用度.首先要看了解幾點(diǎn): 開放性與維護(hù)本錢成正比關(guān)系接口的開放必須帶有使用說明, 這會增加團(tuán)隊(duì)開放的溝通本錢同時一但接口發(fā)生改變將 可能帶來額外的說明性重構(gòu)本錢.在某些情況下我們很容易被高擴(kuò)展性所引誘將很多可能被復(fù)用的功能通過擴(kuò)展接口暴露出來.當(dāng)這種高擴(kuò)展性的誘惑主導(dǎo)了設(shè)計(jì)師的思維, 隨著模塊的增多工程的變大、慢慢地設(shè)計(jì)師就會進(jìn)入自己所創(chuàng)立的注釋惡夢中.開放性與耦合度成正比關(guān)系模塊的開放性接口是具有耦合傳導(dǎo)效應(yīng)的,限制模塊間的耦合度就能在很大程度上限制了系統(tǒng)的
19、耦合度.模塊間的依賴性越小,耦合度越低才更易于變化盡量將耦合度集中在某一兩個模塊中如:Facade模式,而不是分散在各模塊間.耦合度高的模塊自然而然地成 為 核心模塊,而其實(shí)的 外部模塊那么需要保持自身的封閉性,這樣的設(shè)計(jì)就很多容易適對未知的變化.由這兩個正比關(guān)系結(jié)合對實(shí)現(xiàn)本錢的限制上我們做出兩個最為簡單可行的推論:推論1 : 正常情況下請保持圭寸閉,沒有必要的情況下絕不開放推論2 :集中開放性,讓模塊間保持陌生開-閉原那么從理論上來談會有很多內(nèi)容,但實(shí)現(xiàn)起來卻很簡單,就以C#為例限制模塊開放性的最簡單方法就是限制作用域:in ternal , public .3.從函數(shù)/方法設(shè)計(jì)的角度我為認(rèn)
20、為OCP用到極至的情況就是應(yīng)用于方法級,眾所周知:參數(shù)越少的方法越好用.開-閉原那么可以簡單地理解為參數(shù)的多寡與返會值的限制在此我更想談?wù)?開-閉原那么在C#中的應(yīng)用.首先在方法設(shè)計(jì)上, C#給了設(shè)計(jì)人員與開 發(fā)人員一個極大的空間,到了 4.5我們甚至可以使用 async方法來簡單控異步方法,那么 先來總結(jié)一下C#的方法參數(shù)的種類.固定參數(shù): public void methodName(string a, out b, ref c);動態(tài)參數(shù): public void methodName(stri ng a, stri ng b=“ defautlStri ng ")* 可變參數(shù)
21、: public void methodName(params string a);表達(dá)式參數(shù)(方法注入):public void methodName(F un c<stri ng> func.Actio n act);* 泛型參數(shù):public void methodName<T>( T a) where a : class;在C#中我們那么需要從 注入這方面來思考和充分發(fā)揮語言自身的特性,以到達(dá)簡化代碼, 增強(qiáng)易讀性的效果.這里談的 注入主要指兩個方面,一 是 代碼注入二是 類型注入.可擴(kuò)展的局部以執(zhí)行未 開放性.代碼注入就是向方法傳入 代理類就是在方法內(nèi)部開辟出
22、某一知、可變的功能,那么我們就可以對相對 封閉的方法增強(qiáng)其通過泛型方法的使用,我們可以在對類型開放的情況下對類型的通用操作相對地封閉起來,這樣可以在很大程度上利用泛型復(fù)合取代類繼承,降低類的多態(tài)耦合度.里氏替換原那么LSP 但凡基類適用的地方,子類一定適用里氏代換原那么 Liskov Substitution Prin ciple LSP面向?qū)ο笤O(shè)計(jì)的根本原那么之一.里氏代換原那么中說,任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn).LSP是繼承復(fù)用的基石,只有當(dāng)衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被復(fù)用,而衍生類也能夠在基類的根底上增加新的行為.里氏代換原那么是對 開-閉
23、原那么的補(bǔ)充.實(shí)現(xiàn) 開-閉原那么的關(guān)鍵步驟就是抽象化.而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原那么是對實(shí)現(xiàn)抽象化的具體步驟的標(biāo)準(zhǔn).在前文開-閉原那么關(guān)于類設(shè)計(jì)應(yīng)用局部已經(jīng)根本表達(dá)過替換原那么的用法.這個原那么,我 一直是反向理解的,這樣就非常容易運(yùn)用,我是這樣使用的:但凡出現(xiàn)大量子類不適用的成員,子類就應(yīng)該脫離繼承關(guān)系基類中但凡出現(xiàn)大量虛成員,該類就失去成為基類的條件參考: Agile Design Principles: The Liskov Substitution Principle依賴倒轉(zhuǎn)原那么DIP要依賴抽象,不要依賴具體.DIP就像LSP 一樣,原文與譯文其實(shí)都非
24、??拥?這里我就不直接引入原文了,由于 我希望每個讀這篇文章的朋友都能理解并應(yīng)用這些原那么而不是在玩文字游戲.DIP用最為簡單的表述就是:面向接口編程.子類可以引用父類方法或成員,而父類那么絕對不能調(diào)用任何的子類方法或成員.一但上層類調(diào)的方法調(diào)用了子類的方法就會形成依賴環(huán),一般上編譯器會放過依賴環(huán)認(rèn)為這不屬于邏輯錯誤,但具有依賴環(huán)的類結(jié)構(gòu)是無法序列化的在 C#中會直接拋出環(huán)狀引用的異常.通俗點(diǎn): 規(guī)矩是祖宗定的,子孫只能執(zhí)行和完善 ,用這個口決就可以完全掌握此原那么.在過去10年前開發(fā)工具還比擬落后,這是原那么十分重要,而如今可以借助VS.net去找到出這種設(shè)計(jì)錯誤,也可以直接使用 IoC和D
25、I就會自然而充分地尊守此原那么 .接口隔離原那么ISP使用多個專門的接口比適用單一的接口要好架構(gòu)師在邏輯世界就是神,設(shè)計(jì)軟件的過程就是創(chuàng)造邏輯世界,每一個接口就是這個世界中的一種規(guī)那么,類那么是實(shí)現(xiàn)規(guī)那么的做法,實(shí)例就是執(zhí)行規(guī)那么的人.在實(shí)現(xiàn)工作中,我們會經(jīng)常遇到這樣的現(xiàn)象: 一個PM可能同時在跟進(jìn)好幾個工程,或是一個PM要同時充當(dāng)架構(gòu)師、PM、程序員甚至售前的角色,這些苦B們是公司內(nèi)最累的人,同時也是失敗率最高的群體,為什么? 答案顯而易見:人的精力是有限的,專注于某一件事才能真正有成果.同理,在邏輯世界也是一樣的,當(dāng)接口要承載多種的任務(wù),被眾多不同的類所調(diào)用時就會出現(xiàn) 接口過載或者接口污染
26、,'實(shí)現(xiàn)這些接口的類將會產(chǎn)生很高的耦合度,從而代碼會變得難以閱讀,難以理解,也難以變化.別離接口就是隔離了客戶接口的使用者,隔離客戶 就自然降低耦合度.一個完美的世界就應(yīng)該是專人專項(xiàng),讓擅長的人做其擅長的事,在現(xiàn)實(shí)不可能但邏輯世界卻可以.那么在設(shè)計(jì)中如何來把握這種原那么呢?很簡單,當(dāng)一個接口上的方法被多個類調(diào)用時就要警覺了, 如果這些方法間沒有依賴關(guān)系,甚至是不同類別在做不同的事的方法那么就得考慮使用ISP原那么將接口別離成兩個獨(dú)立的接口,使接口的耦合度從1.n降低至 1.1.合成/聚合復(fù)用原那么CARP要盡量使用合成/聚合,盡量不要使用繼承復(fù)用原那么是一個很容易被忽略而又極其重要的原
27、那么,這個原那么具有非常深遠(yuǎn)的架構(gòu)意義.對于小型工程類庫規(guī)模小即使違反此原那么也不會帶來什么危害,但當(dāng)構(gòu)建大規(guī)模的類庫數(shù)百甚至數(shù)千個類時,這個原那么就可以預(yù)防出現(xiàn)繼承失控、過度膨脹、無法重構(gòu)等的風(fēng)險,也決定了整個結(jié)構(gòu)的可重用性和可維護(hù)性.在定義中它只是一句簡單的話,但從繼承、合成與聚合就引出了一系列的內(nèi)容,涵蓋多種設(shè)計(jì)模式和附帶多個更小層級的應(yīng) 用原那么.注:關(guān)于合成/聚合的好處請去百度吧,關(guān)于 白箱復(fù)用與 黑箱復(fù)用都被轉(zhuǎn)爛了首先要正確的選擇合成/復(fù)用和繼承,必須透徹地理解里氏替換原那么和Coad法那么.Coad法那么由Peter Coad 提出,總結(jié)了一些什么時候使用繼承作為復(fù)用工具的條件.
28、Coad法那么:只有當(dāng)以下Coad條件全部被滿足時,才應(yīng)當(dāng)使用繼承關(guān)系:1. 子類是超類的一個特殊種類,而不是超類的一個角色.區(qū)分“ HasA和“IsA.只有“IsA關(guān)系才符合繼承關(guān)系,“Ha&A關(guān)系應(yīng)當(dāng)用聚合來描述.1. “A代表一個類是另外一個類的一種;2. “ HasA代表一個類是另外一個類的一個角色,而不是另外一個類的特殊 種類.永遠(yuǎn)不會出現(xiàn)需要將子類換成另外一個類的子類的情況.如果不能肯定將來是否會變成另外一個子類的話,就不要使用繼承.子類具有擴(kuò)展超類的責(zé)任,而不是具有置換掉override 或注銷掉Nullify 超類的責(zé)任.如果一個子類需要大量的置換掉超類的行為,那么這個
29、類就不應(yīng)該 是這個超類的子類.注:在C#中含有new 的方法、屬性和內(nèi)部實(shí)現(xiàn)單一基類接口就相當(dāng)于 Nullify只有在分類學(xué)角度上有意義時,才可以使用繼承.不要從工具類繼承.對于一個老手Coad法那么只是一種總結(jié),很容易理解與運(yùn)用,但如果你是一個架構(gòu)新手 Coad 法那么就很是坑爹(我的理解力很低,當(dāng)年我就被坑了很久)! 所以我想另辟蹊徑從其它角度 來嘗試解釋這個原那么.繼承限制繼承是面向?qū)ο蟮囊环N重要構(gòu)型,復(fù)用原那么只告訴我們盡量不使用繼承而不是將繼承魔鬼 化,在很多場景下,小結(jié)構(gòu)繼承是非常常見與易讀的.只是,我們需要了解繼承的子代的增加是以整個類結(jié)構(gòu)的復(fù)雜度增加n次方在遞增,隨著子代層級的
30、增多類家族結(jié)構(gòu)的變化就越來越難.其實(shí),我們可以找一些自已手上的例子來看看,如果有3代以上繼承關(guān)系的類,看看最小的子孫類與基類之間是否已經(jīng)有點(diǎn)面目全非?這一點(diǎn)與人類的繁衍與繼承是很類似的.再深入一點(diǎn)就是如果向最頂層的基類進(jìn)行擴(kuò)展,是那么能完全適用替換原那么呢?更改高層級結(jié)構(gòu)時是否有 揮舞大刀般的沉重感?對是否有勇氣對穩(wěn)定的祖代類重構(gòu)?/聚合推論:盡可能預(yù)防出現(xiàn)三代以外的繼承關(guān)系,否那么應(yīng)考慮合成合成與 聚合從字面意義上去理解是我一直以來都無法正確理解的內(nèi)容.可能是我語文水平實(shí)在太低的緣故吧,對Composite 和Aggregation兩個單詞我反而能在維基百科上找到準(zhǔn)確的定義.合成 (Comp
31、osite )- 值聚合 (Aggregati on by value)我的通俗定義:合成的過程是在類的構(gòu)造過程中(構(gòu)造函數(shù)或外部的構(gòu)造方法)在運(yùn)行期將值或其它類實(shí)例組裝到合成類內(nèi)(通過變量或?qū)傩?Hold住)如:public classKeyboardpublic classMousepublic classMonitorpublic classComputerprivate Keyboard keyboard;private Mouse mouse;private Monitor monitor;public Computer()this.keyboard=new Keyboard();t
32、his.mouse=new Mouse(); this.m on itor =new Mon itor();由這個例子可見,所謂的 值(Value )"通過構(gòu)造函數(shù)合成為“Computer的內(nèi)部成員,有如將各個功能單一的部件裝配成為一個功能強(qiáng)大的產(chǎn)品.所有的依賴都被關(guān)在構(gòu)造函數(shù)內(nèi),如果將依賴外置就可以運(yùn)用工廠(Factory Pattern) 和合成模式(Composite Pattern)進(jìn)行演變.public classltem;public classKeyboard:Itempublic classMouse:ltem public classMonitor:ltempubl
33、ic ComputerFactorypublic Item Keyboard. return new Keyboard.; public Item Monitor() return new Monitor(); public Item Mouse() return new Mouse(); public classComputerpublic List<Item> Items getset;public Computer(ComputerFactory factory) this.ltems.Add(factory.Keyboard(); this.ltems.Add(factory.Mouse(); this.Items.Add(factory.Mo nitor();阪通過簡單的演變,就可以將Computer 1-3 的耦合變成1-1的耦合,所有的依賴都集中到ComputerFactory 上,只需要繼承ComputerFactory創(chuàng)立更多的工廠傳入 Computer類就可以生產(chǎn)出各種各樣的Computer 實(shí)例,而無需更改Computer 的任何
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 班級歷史文化傳承的舉措計(jì)劃
- 大班班級日常管理的注意事項(xiàng)計(jì)劃
- 2025年玉米酒精糟回收蛋白飼料成套設(shè)備(DDGS)項(xiàng)目建議書
- 2025年異步轉(zhuǎn)移模式寬帶交換機(jī)項(xiàng)目建議書
- 2025年不停電電源(UPS)項(xiàng)目合作計(jì)劃書
- 2025年中國文創(chuàng)產(chǎn)品行業(yè)發(fā)展策略、市場環(huán)境及前景研究分析報告
- 2025年鼠抗腫瘤相關(guān)抗原單克隆抗體項(xiàng)目合作計(jì)劃書
- 客戶資料查詢權(quán)限嚴(yán)格把控
- 簡易私人承包合同
- 電纜電線采購合同書
- 幼兒園課件:時鐘國王
- 最值問題-阿氏圓
- 社區(qū)獲得性肺炎教學(xué)查房
- 現(xiàn)金盤點(diǎn)表完整版
- 病例展示(皮膚科)
- 7、核生化防護(hù)教案
- 海上鋼琴師英語PPT
- GB/T 39750-2021光伏發(fā)電系統(tǒng)直流電弧保護(hù)技術(shù)要求
- GB/T 16839.1-2018熱電偶第1部分:電動勢規(guī)范和允差
- 教科版五年級科學(xué)下冊【全冊全套】課件
- 大數(shù)據(jù)專業(yè)實(shí)習(xí)報告范文共5篇
評論
0/150
提交評論