[轉(zhuǎn)]S.O.L.I.D

面向?qū)ο笤O(shè)計的原則(OOD&OOP)主要分為兩大類歪架,一類是面向類的,另一類是面向包的夺鲜。設(shè)計模式基本都是圍繞面向類的幾個原則的實踐皆尔,而面向包的幾個原則主要體現(xiàn)在架構(gòu)模式中。

S.O.L.I.D

Bob大叔(Robert C. Martin)的大名如雷貫耳币励,相信大部分在進擊中的開發(fā)者都有閱讀過經(jīng)典著作《敏捷軟件開發(fā)》的經(jīng)歷慷蠕,受益匪淺。

在面向?qū)ο蟮某绦虻脑O(shè)計和開發(fā)過程中時食呻,有5個原則非常重要流炕,此外還有一個法則我們應(yīng)該盡量去遵守它。

1仅胞、單一職責(zé)原則(SRP每辟,The Single Responsibility Principle)
2、開放封閉原則(OCP干旧,The Open Closed Principle)
3渠欺、里氏替換原則(LSP,The Liskov Substitution Principle)
4椎眯、依賴倒置原則(DIP挠将,The Dependency Inversion Principle)
5、接口分離原則(ISP编整,The Interface Segregation Principle)
6舔稀、迪米特法則(LoD,The Law of Demeter闹击、LKP)
SRP

A class should have only one reason to change.
一個類應(yīng)該僅有一個引起它變化的原因镶蹋。

SRP是所有原則中最簡單的一個,概念簡潔易懂赏半。但卻也是最難正確運用贺归,或者說是最容易過度使用的原則。

一方面断箫,因為SRP把職責(zé)定義成了變化的原因拂酣,如果我們能夠找到多于一個的動機去改變一個類,那么這個類就具有多于一個的職責(zé)仲义。比如開發(fā)者經(jīng)常會習(xí)慣性的把職責(zé)歸類式的結(jié)合在一起婶熬,而正確的做法是發(fā)現(xiàn)職責(zé)并把這些職責(zé)相互分離。

另一方面埃撵,如果程序的變化方式總是導(dǎo)致N個職責(zé)(N>1)同時變化赵颅,那么就沒必要分離它們了。在這里有一個推論:僅當變化發(fā)生時暂刘,變化的軸線才具有實際的意義饺谬。在實際的設(shè)計和開發(fā)過程中,一定要把握好分離“單個”職責(zé)的度谣拣,所謂過猶不及募寨,過度的分離只能適得其反族展,違背了面向?qū)ο蟮姆庋b思想。

OCP

Software entities(classes,modules,functions,etc.) should be open for extension, but closed for modification.
軟件實體(如類拔鹰、模塊仪缸、函數(shù)等)應(yīng)該對擴展開放,對修改關(guān)閉列肢。

OCP是整個面向?qū)ο笤O(shè)計的核心恰画。它代表了靈活性、可重用性和可維護性例书。

乍一看锣尉,兩個特征似乎有所矛盾,擴展模塊的功能通常是以修改模塊的源代碼作為手段决采。但是,我們有“抽象”坟奥!通過創(chuàng)建穩(wěn)定的但又能描述一組任意個可能行為的抽象基類树瞭,并將具體的行為實現(xiàn)為派生類,這種做法能很好的解決開放擴展的問題爱谁。主要是針對軟件中頻繁變化的那部分作出合理的抽象晒喷。

當然,創(chuàng)建和使用抽象會增加軟件復(fù)雜性和團隊的精力访敌,所以肆意的進行抽象顯然并不是一個好設(shè)計凉敲,簡直是折磨人。除非你有強大的智商優(yōu)越感寺旺,但是面對廣大平凡質(zhì)樸的程序員爷抓,還請手下留情。

拒絕不成熟的抽象和抽象本身一樣重要阻塑。

LSP

Derived types must be completely substitutable for their base types.
子類型必須能夠完全的替換掉它們的基類型蓝撇。

LSP是使OCP成為可能的主要原則之一,也是繼承層次特征的主要設(shè)計原則陈莽。

一個軟件實體如果使用的是一個父類的話,那么一定適用于其子類,而且它察覺不出父類對象和子類對象的區(qū)別畏纲。也就是說筛武,在軟件中,把父類都替換成它的子類私植,程序行為沒有或者不發(fā)生變化忌栅。也就是說,只有當子類可以替換掉父類兵琳,軟件的功能不受到影響時狂秘,父類才能真正的被復(fù)用骇径,而子類也能夠真正的在父類的基礎(chǔ)上增加新的行為。

子類型的可替換性使得使用基類型表示的模塊在無需修改的情況下就可以擴展者春∑葡危可替換性可以通過顯示或者隱式的契約來定義。

DIP

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
高層模塊不應(yīng)該依賴于低層模塊钱烟,兩者都應(yīng)該依賴于抽象
B. Abstractions should not depend on details. Details should depend on abstractions.
抽象不應(yīng)該依賴于細節(jié)晰筛,細節(jié)應(yīng)該依賴于抽象

DIP是面向?qū)ο笤O(shè)計的標志。

依賴倒置原則是實現(xiàn)許多面向?qū)ο蠹夹g(shù)所宣稱的好處的基本低層機制拴袭,他的正確應(yīng)用對于創(chuàng)建可重用的框架來說是必須的读第。同時它對于構(gòu)建在變化面前富有彈性的代碼也是非常重要的,由于抽象和細節(jié)彼此隔離拥刻,所以代碼也非常容易維護怜瞒。

針對接口編程,而不要對實現(xiàn)編程般哼。倒置接口的所有權(quán)吴汪。

LSP和DIP乍一看還有點相似,其實蒸眠,他們還是有區(qū)別的:

兩個原則所站的角度不同漾橙。LSP是站在模式對象的角度,而DIP則是站在客戶端程序的角度楞卡;模式對象一方將“相對多變的”子類視同它的接口(或父類)霜运,而客戶程序依賴的內(nèi)容是“相對穩(wěn)定”的接口。

ISP

Clients should not be forced to depend upon interfaces that they don't use.
不應(yīng)該強迫客戶程序依賴并未使用的接口蒋腮。

ISP有效的降低了程序間的耦合性淘捡,提高了程序集的內(nèi)聚性。避免了接口污染徽惋。

客戶程序應(yīng)該僅僅依賴于他們實際調(diào)用的方法案淋。分離客戶就是分離接口。通常我們可以使用委托或者使用多重繼承來分離接口险绘。

接口隔離原則不是單純的多余或是不多余踢京,從設(shè)計的角度來衡量,它要依據(jù)業(yè)務(wù)領(lǐng)域的需要判斷倒是是否真的“多余”宦棺,確保在每個領(lǐng)域背景下貫徹不去依賴用不到的方法瓣距。通過把胖類的接口分解為多個特定于客戶程序的接口,可以實現(xiàn)這個目標代咸。有效的解除了客戶程序和它們沒有調(diào)用到的方法間的依賴關(guān)系蹈丸。

客戶程序看到的應(yīng)該是多個具有內(nèi)聚接口的抽象基類。

LoD(LKP)

A. Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
每一個軟件單位對其他的單位都只有最少的知識,而且局限于那些與本單位密切相關(guān)的軟件單位逻杖。
B. Each unit should only talk to its friends; don't talk to strangers.
C. Only talk to your immediate friends.

迪米特法則又稱為最少知識原則奋岁。主要有三層意思,就是讓調(diào)用者對于目標對象的知識最少荸百,而且只和你的直接朋友對話闻伶,千萬不要和陌生人說話。

該法則因在《程序員的修煉之道》一書中提及而聲名鵲起廣為人知够话。其初衷在于降低類之間的耦合蓝翰,但是由于通過友元類來建立一個類和其他類的聯(lián)系,或是減少對其他類的依賴女嘲,這導(dǎo)致了在一定程度上增加了系統(tǒng)的復(fù)雜度畜份。

小結(jié)

這些原則是數(shù)十年軟件工程經(jīng)驗來之不易的結(jié)果。是眾多開發(fā)人員和研究人員思想和著作的結(jié)晶欣尼。我們應(yīng)該牢記面向?qū)ο笤O(shè)計的原則爆雹,理解OO的設(shè)計思路。因為它們有助于開發(fā)人員消除拙劣的設(shè)計和代碼臭味愕鼓,并能有效的幫助開發(fā)人員構(gòu)建出最適合于當前特性集的設(shè)計顶别。

Bob大叔建議:在日常工作中,只有當出現(xiàn)“臭味”時我們才會去使用它拒啰,如果只是因為它是一個原則就無條件的遵循它那是錯誤的,過分的遵循這些原則會導(dǎo)致不必要的復(fù)雜性和設(shè)計臭味完慧。
原文

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谋旦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屈尼,更是在濱河造成了極大的恐慌册着,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脾歧,死亡現(xiàn)場離奇詭異甲捏,居然都是意外死亡,警方通過查閱死者的電腦和手機鞭执,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門司顿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兄纺,你說我怎么就攤上這事大溜。” “怎么了估脆?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵钦奋,是天一觀的道長。 經(jīng)常有香客問我,道長付材,這世上最難降的妖魔是什么朦拖? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮厌衔,結(jié)果婚禮上璧帝,老公的妹妹穿的比我還像新娘。我一直安慰自己葵诈,他們只是感情好裸弦,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著作喘,像睡著了一般理疙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泞坦,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天窖贤,我揣著相機與錄音,去河邊找鬼贰锁。 笑死赃梧,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的豌熄。 我是一名探鬼主播授嘀,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼锣险!你這毒婦竟也來了蹄皱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤芯肤,失蹤者是張志新(化名)和其女友劉穎巷折,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崖咨,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡锻拘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了击蹲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片署拟。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖际邻,靈堂內(nèi)的尸體忽然破棺而出芯丧,到底是詐尸還是另有隱情,我是刑警寧澤世曾,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布缨恒,位于F島的核電站谴咸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏骗露。R本人自食惡果不足惜岭佳,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萧锉。 院中可真熱鬧珊随,春花似錦、人聲如沸柿隙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禀崖。三九已至衩辟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間波附,已是汗流浹背艺晴。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留掸屡,地道東北人封寞。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像仅财,于是被迫代替她去往敵國和親狈究。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容