設(shè)計(jì)模式之設(shè)計(jì)原則

SOLID原則是由五個(gè)設(shè)計(jì)原則組成:單一職責(zé)原則(SRP)嫉沽,開閉原則(OCP),里式替換原則(LSP)俏竞,接口隔離原則(ISP)绸硕,依賴反轉(zhuǎn)原則(DIP)

單一職責(zé)原則(SRP)

概念

單一職責(zé)原則的英文是 Single Responsibility Principle,縮寫為 SRP魂毁。

一個(gè)類只負(fù)責(zé)完成一個(gè)職責(zé)或者功能玻佩。不要設(shè)計(jì)大而全的類,要設(shè)計(jì)粒度小席楚、功能單一的類夺蛇。單一職責(zé)原則是為了實(shí)現(xiàn)代碼高內(nèi)聚、低耦合酣胀,提高代碼的復(fù)用性刁赦、可讀性娶聘、可維護(hù)性。

如何判斷類的職責(zé)是否足夠單一甚脉?

不同的應(yīng)用場景丸升、不同階段的需求背景、不同的業(yè)務(wù)層面牺氨,對同一個(gè)類的職責(zé)是否單一狡耻,可能會有不同的判定結(jié)果。

一些側(cè)面的判斷指標(biāo)更具有指導(dǎo)意義和可執(zhí)行性猴凹,比如夷狰,出現(xiàn)下面這些情況就有可能說明這類的設(shè)計(jì)不滿足單一職責(zé)原則:

  • 類中的代碼行數(shù)、函數(shù)或者屬性過多郊霎;

  • 類依賴的其他類過多沼头,或者依賴類的其他類過多;

  • 私有方法過多书劝;

  • 比較難給類起一個(gè)合適的名字进倍;

  • 類中大量的方法都是集中操作類中的某幾個(gè)屬性。

類的職責(zé)是否設(shè)計(jì)得越單一越好购对?

單一職責(zé)原則是為了實(shí)現(xiàn)代碼高內(nèi)聚猾昆、低耦合,如果拆分得過細(xì)骡苞,實(shí)際上會適得其反垂蜗,反倒會降低內(nèi)聚性,也會影響代碼的可維護(hù)性解幽。

開閉原則(OCP)

概念

開閉原則的英文全稱是 Open Closed Principle贴见,簡寫為 OCP。

軟件實(shí)體(模塊亚铁、類蝇刀、方法等)應(yīng)該“對擴(kuò)展開放、對修改關(guān)閉”徘溢。

添加一個(gè)新的功能吞琐,應(yīng)該是通過在已有代碼基礎(chǔ)上擴(kuò)展代碼(新增模塊、類然爆、方法站粟、屬性等),而非修改已有代碼(修改模塊曾雕、類奴烙、方法、屬性等)的方式來完成。關(guān)于定義切诀,我們有兩點(diǎn)要注意揩环。第一點(diǎn)是,開閉原則并不是說完全杜絕修改幅虑,而是以最小的修改代碼的代價(jià)來完成新功能的開發(fā)丰滑。第二點(diǎn)是,同樣的代碼改動倒庵,在粗代碼粒度下褒墨,可能被認(rèn)定為“修改”;在細(xì)代碼粒度下擎宝,可能又被認(rèn)定為“擴(kuò)展”郁妈。

如何做到“對擴(kuò)展開放、修改關(guān)閉”绍申?

我們要時(shí)刻具備擴(kuò)展意識噩咪、抽象意識、封裝意識失晴,在寫代碼的時(shí)候剧腻,多思考這段代碼未來可能有哪些需求變更拘央,如何設(shè)計(jì)代碼結(jié)構(gòu)涂屁,事先留好擴(kuò)展點(diǎn),以便將新的代碼靈活地插入到擴(kuò)展點(diǎn)上灰伟。

23 種經(jīng)典設(shè)計(jì)模式拆又,大部分都是為了解決代碼的擴(kuò)展性問題而總結(jié)出來的,都是以開閉原則為指導(dǎo)原則的栏账。最常用來提高代碼擴(kuò)展性的方法有:多態(tài)帖族、依賴注入、基于接口而非實(shí)現(xiàn)編程挡爵,以及大部分的設(shè)計(jì)模式(比如竖般,裝飾、策略茶鹃、模板涣雕、職責(zé)鏈、狀態(tài))闭翩。

里式替換原則(LSP)

概念

里式替換原則的英文翻譯是:Liskov Substitution Principle挣郭,縮寫為 LSP。

子類對象能夠替換程序中父類對象出現(xiàn)的任何地方疗韵,并且保證原來程序的邏輯行為不變及正確性不被破壞兑障。

里式替換原則是用來指導(dǎo),繼承關(guān)系中子類該如何設(shè)計(jì)的一個(gè)原則。理解里式替換原則流译,最核心的就是理解“design by contract逞怨,按照協(xié)議來設(shè)計(jì)”這幾個(gè)字。父類定義了函數(shù)的“約定”(或者叫協(xié)議)福澡,那子類可以改變函數(shù)的內(nèi)部實(shí)現(xiàn)邏輯骇钦,但不能改變函數(shù)原有的“約定”。這里的約定包括:函數(shù)聲明要實(shí)現(xiàn)的功能竞漾;對輸入眯搭、輸出、異常的約定业岁;甚至包括注釋中所羅列的任何特殊說明鳞仙。

里式替換原則跟多態(tài)的區(qū)別

雖然從定義描述和代碼實(shí)現(xiàn)上來看,多態(tài)和里式替換有點(diǎn)類似笔时,但它們關(guān)注的角度是不一樣的棍好。多態(tài)是面向?qū)ο缶幊痰囊淮筇匦裕彩敲嫦驅(qū)ο缶幊陶Z言的一種語法允耿。它是一種代碼實(shí)現(xiàn)的思路借笙。而里式替換是一種設(shè)計(jì)原則,用來指導(dǎo)繼承關(guān)系中子類該如何設(shè)計(jì)较锡,子類的設(shè)計(jì)要保證在替換父類的時(shí)候业稼,不改變原有程序的邏輯及不破壞原有程序的正確性。

接口隔離原則(ISP)

概念

接口隔離原則的英文翻譯是“ Interface Segregation Principle”蚂蕴,縮寫為 ISP低散。

客戶端不應(yīng)該強(qiáng)迫依賴它不需要的接口。其中的“客戶端”骡楼,可以理解為接口的調(diào)用者或者使用者熔号。

接口的設(shè)計(jì)要盡量單一,不要讓接口的實(shí)現(xiàn)類和調(diào)用者鸟整,依賴不需要的接口函數(shù)引镊。

接口隔離原則與單一職責(zé)原則的區(qū)別

單一職責(zé)原則針對的是模塊、類篮条、接口的設(shè)計(jì)弟头。接口隔離原則相對于單一職責(zé)原則,一方面更側(cè)重于接口的設(shè)計(jì)兑燥,另一方面它的思考角度也是不同的亮瓷。接口隔離原則提供了一種判斷接口的職責(zé)是否單一的標(biāo)準(zhǔn):通過調(diào)用者如何使用接口來間接地判定。如果調(diào)用者只使用部分接口或接口的部分功能降瞳,那接口的設(shè)計(jì)就不夠職責(zé)單一嘱支。

依賴反轉(zhuǎn)原則(DIP)

概念

依賴反轉(zhuǎn)原則蚓胸。依賴反轉(zhuǎn)原則的英文翻譯是 Dependency Inversion Principle,縮寫為 DIP除师。

高層模塊不要依賴低層模塊沛膳。高層模塊和低層模塊應(yīng)該通過抽象來互相依賴。除此之外汛聚,抽象不要依賴具體實(shí)現(xiàn)細(xì)節(jié)锹安,具體實(shí)現(xiàn)細(xì)節(jié)依賴抽象。

所謂高層模塊和低層模塊的劃分倚舀,簡單來說就是叹哭,在調(diào)用鏈上,調(diào)用者屬于高層痕貌,被調(diào)用者屬于低層风罩。

控制反轉(zhuǎn)(IOC)

這里的“控制”指的是對程序執(zhí)行流程的控制,而“反轉(zhuǎn)”指的是在沒有使用框架之前舵稠,程序員自己控制整個(gè)程序的執(zhí)行超升。在使用框架之后,整個(gè)程序的執(zhí)行流程可以通過框架來控制哺徊。流程的控制權(quán)從程序員“反轉(zhuǎn)”到了框架室琢。

實(shí)現(xiàn)控制反轉(zhuǎn)的方法有很多,控制反轉(zhuǎn)并不是一種具體的實(shí)現(xiàn)技巧落追,而是一個(gè)比較籠統(tǒng)的設(shè)計(jì)思想盈滴,一般用來指導(dǎo)框架層面的設(shè)計(jì)。

依賴注入(DI)

什么是依賴注入呢淋硝?我們用一句話來概括就是:不通過 new() 的方式在類內(nèi)部創(chuàng)建依賴類對象雹熬,而是將依賴的類對象在外部創(chuàng)建好之后宽菜,通過構(gòu)造函數(shù)谣膳、函數(shù)參數(shù)等方式傳遞(或注入)給類使用。

KISS 原則

概念

KISS 原則铅乡。英文是 Keep It Simple and Stupid继谚,縮寫為 KISS。

盡量保持簡單

KISS 原則中的“簡單”并不是以代碼行數(shù)來考量的阵幸。代碼行數(shù)越少并不代表代碼越簡單花履,我們還要考慮邏輯復(fù)雜度、實(shí)現(xiàn)難度挚赊、代碼的可讀性等诡壁。而且,本身就復(fù)雜的問題荠割,用復(fù)雜的方法解決妹卿,并不違背 KISS 原則旺矾。除此之外,同樣的代碼夺克,在某個(gè)業(yè)務(wù)場景下滿足 KISS 原則箕宙,換一個(gè)應(yīng)用場景可能就不滿足了。

對于如何寫出滿足 KISS 原則的代碼

  • 不要使用同事可能不懂的技術(shù)來實(shí)現(xiàn)代碼铺纽;

  • 不要重復(fù)造輪子柬帕,要善于使用已經(jīng)有的工具類庫;

  • 不要過度優(yōu)化狡门。

DRY 原則

概念

DRY 原則為Don’t Repeat Yourself

不要重復(fù)造輪子

實(shí)現(xiàn)邏輯重復(fù)陷寝,但功能語義不重復(fù)的代碼,并不違反 DRY 原則其馏。實(shí)現(xiàn)邏輯不重復(fù)盼铁,但功能語義重復(fù)的代碼,也算是違反 DRY 原則尝偎。除此之外饶火,代碼執(zhí)行重復(fù)也算是違反 DRY 原則。

提高代碼可復(fù)用性的一些方法

  • 減少代碼耦合

  • 滿足單一職責(zé)原則

  • 模塊化

  • 業(yè)務(wù)與非業(yè)務(wù)邏輯分離

  • 通用代碼下沉

  • 繼承致扯、多態(tài)肤寝、抽象、封裝

  • 應(yīng)用模板等設(shè)計(jì)模式

我們在第一次寫代碼的時(shí)候抖僵,如果當(dāng)下沒有復(fù)用的需求鲤看,而未來的復(fù)用需求也不是特別明確,并且開發(fā)可復(fù)用代碼的成本比較高耍群,那我們就不需要考慮代碼的復(fù)用性义桂。在之后開發(fā)新的功能的時(shí)候,發(fā)現(xiàn)可以復(fù)用之前寫的這段代碼蹈垢,那我們就重構(gòu)這段代碼慷吊,讓其變得更加可復(fù)用。

相比于代碼的可復(fù)用性曹抬,DRY 原則適用性更強(qiáng)一些溉瓶。我們可以不寫可復(fù)用的代碼,但一定不能寫重復(fù)的代碼谤民。

迪米特法則(LOD)

概念

迪米特法則的英文翻譯是:Law of Demeter堰酿,縮寫是 LOD。它還有另外一個(gè)更加達(dá)意的英文翻譯為:The Least Knowledge Principle张足。

最小知識原則

每個(gè)模塊只應(yīng)該了解那些與它關(guān)系密切的模塊的有限知識触创。

不該有直接依賴關(guān)系的類之間,不要有依賴为牍。有依賴關(guān)系的類之間哼绑,盡量只依賴必要的接口顺饮。迪米特法則是希望減少類之間的耦合,讓類越獨(dú)立越好凌那。每個(gè)類都應(yīng)該少了解系統(tǒng)的其他部分兼雄。一旦發(fā)生變化,需要了解這一變化的類就會比較少帽蝶。

如何理解“高內(nèi)聚赦肋、松耦合”?

所謂高內(nèi)聚励稳,就是指相近的功能應(yīng)該放到同一個(gè)類中佃乘,不相近的功能不要放到同一類中。相近的功能往往會被同時(shí)修改驹尼,放到同一個(gè)類中趣避,修改會比較集中。

所謂松耦合指的是新翎,在代碼中程帕,類與類之間的依賴關(guān)系簡單清晰。即使兩個(gè)類有依賴關(guān)系地啰,一個(gè)類的代碼改動也不會或者很少導(dǎo)致依賴類的代碼改動愁拭。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市亏吝,隨后出現(xiàn)的幾起案子岭埠,更是在濱河造成了極大的恐慌,老刑警劉巖蔚鸥,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惜论,死亡現(xiàn)場離奇詭異,居然都是意外死亡止喷,警方通過查閱死者的電腦和手機(jī)馆类,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來启盛,“玉大人蹦掐,你說我怎么就攤上這事〗┐常” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵藤滥,是天一觀的道長鳖粟。 經(jīng)常有香客問我,道長拙绊,這世上最難降的妖魔是什么向图? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任泳秀,我火速辦了婚禮,結(jié)果婚禮上榄攀,老公的妹妹穿的比我還像新娘嗜傅。我一直安慰自己,他們只是感情好檩赢,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布吕嘀。 她就那樣靜靜地躺著,像睡著了一般贞瞒。 火紅的嫁衣襯著肌膚如雪偶房。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天军浆,我揣著相機(jī)與錄音棕洋,去河邊找鬼。 笑死乒融,一個(gè)胖子當(dāng)著我的面吹牛掰盘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赞季,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼庆杜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了碟摆?” 一聲冷哼從身側(cè)響起晃财,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎典蜕,沒想到半個(gè)月后断盛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愉舔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年钢猛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轩缤。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡命迈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出火的,到底是詐尸還是另有隱情壶愤,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布馏鹤,位于F島的核電站征椒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏湃累。R本人自食惡果不足惜勃救,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一碍讨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蒙秒,春花似錦勃黍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至益兄,卻和暖如春锻梳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背净捅。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工疑枯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛔六。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓荆永,卻偏偏與公主長得像,于是被迫代替她去往敵國和親国章。 傳聞我的和親對象是個(gè)殘疾皇子具钥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

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