真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

架構(gòu)設(shè)計(jì)的五大原則-SOLID

1.背景

最近在讀《架構(gòu)整潔之道》這一本書,這本書的確寫得不錯(cuò),最近也沒有更新文章,一方面再忙工作,另一方面也再啃一些書。當(dāng)然文章還是得更新,《架構(gòu)整潔之道》里面有些有意思的內(nèi)容我會(huì)提取出來外加自己的思考。在這本書里面的第三章介紹了設(shè)計(jì)原則,這部分我覺得對(duì)于大家的平時(shí)工作都比較有用。

創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),站前企業(yè)網(wǎng)站建設(shè),站前品牌網(wǎng)站建設(shè),網(wǎng)站定制,站前網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,站前網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

2. 設(shè)計(jì)原則

想必大家在學(xué)習(xí)面向?qū)ο蟮臅r(shí)候,都學(xué)習(xí)過下面幾大原則:

  • SRP 單一職責(zé):該設(shè)計(jì)原則是基于康威定律的推論,每個(gè)軟件模塊有且只有一個(gè)被更改的理由。

  • OCP 開閉原則:對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。

  • LSP 里氏替換原則:任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。

  • ISP 接口隔離原則:在設(shè)計(jì)中需要避免不需要的依賴。

  • DIP 依賴反轉(zhuǎn)原則:高層策略性代碼不應(yīng)該依賴底層細(xì)節(jié)的代碼,而應(yīng)該是底層細(xì)節(jié)代碼依賴高層策略。

這五個(gè)原則也被稱為,SOLID原則取的是他們的首字母。這個(gè)也是我們做一個(gè)好設(shè)計(jì)的基礎(chǔ),接下來會(huì)依次對(duì)其進(jìn)行解釋。

3.SRP:單一職責(zé)

SRP很容易被大家從字面意思無界,并不是每個(gè)模塊只做一個(gè)事,而是每個(gè)模塊的變化原因只有一個(gè)。在書中對(duì)于SRP最后的解釋是:

任何一個(gè)軟件模塊都應(yīng)該只對(duì)某一類行為者(有共同需求的人)負(fù)責(zé)。

這里的軟件模塊指的就是一個(gè)源代碼文件或者一組緊密相關(guān)的函數(shù)和數(shù)據(jù)結(jié)構(gòu)。SRP原則應(yīng)該是大家運(yùn)用得最多的原則之一。在書中舉了一個(gè)例子,有一個(gè)Employee類其中有三個(gè)函數(shù):

  • calculatePay():計(jì)算工資,由財(cái)務(wù)部門制定,需要向CFO匯報(bào)。

  • reportHours():計(jì)算工時(shí),人力資源制定,向COO匯報(bào)

  • save():由DBA制定,向CTO匯報(bào)。

這里三個(gè)函數(shù)都放在了Employee類中,其實(shí)也就是把三個(gè)行為者的行為都耦合在了一起。一般來說計(jì)算工資,會(huì)獲取正常工時(shí),而計(jì)算工時(shí)也會(huì)獲取工時(shí),這兩個(gè)函數(shù)都依賴了一個(gè)獲取工時(shí)的方法,如果財(cái)務(wù)部門計(jì)算工資時(shí),想修改邏輯,看大家辛苦了1個(gè)小時(shí)當(dāng)1.1個(gè)小時(shí)發(fā)工資,這個(gè)時(shí)候修改了這個(gè)獲取工時(shí)的方法,但是HR部門并不需要這個(gè)修改,這個(gè)時(shí)候就會(huì)導(dǎo)致reportHours()這個(gè)方法出現(xiàn)數(shù)據(jù)錯(cuò)誤。所以這個(gè)時(shí)候就需要將不同行為者的代碼就行拆分。

3.1 如何解決

在書中給出了第一個(gè)解決方法:

設(shè)計(jì)出三個(gè)類,每個(gè)類都只與一個(gè)行為者相關(guān)。這種問題的壞處是,程序員需要在程序里處理三個(gè)類,這里還介紹了使用門面模式的方法,讓我們只需要在我們使用的地方使用一個(gè)類即可:

架構(gòu)設(shè)計(jì)的五大原則-SOLID

這樣的話我們就不需要關(guān)心其他三個(gè)類,直接調(diào)用門面模式的方法即可。

3.2 實(shí)際場(chǎng)景

在實(shí)際場(chǎng)景中微服務(wù)可以算作是SRP的思想,雖然每一個(gè)微服務(wù)不止一個(gè)類,但是其整個(gè)服務(wù)也可以看做是一個(gè)模塊,而每個(gè)一個(gè)模塊基本也只于一個(gè)行為者相關(guān)。在我們的代碼中可以使用3.1中所描述的方法來進(jìn)行SRP的實(shí)現(xiàn)。

SRP的好處:

  • 修改代碼容易,由于不需要考慮修改代碼是否會(huì)影響其他業(yè)務(wù)所以是很容易的。

  • 更加容易維護(hù),維護(hù)一個(gè)什么邏輯都有的代碼明顯比維護(hù)一個(gè)單一職責(zé)的代碼難得多。

  • 容易發(fā)現(xiàn)問題,當(dāng)出現(xiàn)問題的時(shí)候,由于職責(zé)清晰,可以比較容易的定位。

  • 松耦合,職責(zé)分離,耦合程度比較低。

4.OCP:開閉原則

在這本書中講述OCP可能和大家從一些資料上面看的有點(diǎn)不同。一般大家所認(rèn)為的開閉原則,應(yīng)該將那些容易變化的部分進(jìn)行抽象,利用對(duì)抽象的多個(gè)實(shí)現(xiàn)來進(jìn)行對(duì)擴(kuò)展開放,而不是直接在類中去修改。

這里我用吃飯的例子來列舉:

每個(gè)人一天都會(huì)吃三餐,早餐,午餐,晚餐,但是隨著時(shí)代的進(jìn)步,又出現(xiàn)了下午茶,宵夜等,現(xiàn)在一天就不止三餐,那么其實(shí)我們就需要在這個(gè)類中去添加喝下午茶方法,吃宵夜方法,這樣就導(dǎo)致我們沒增加一個(gè)餐的種類就需要添加一個(gè)方法,在將SRP的時(shí)候我們有個(gè)例子,在同一個(gè)類中修改方法的時(shí)候容易修改其他業(yè)務(wù)邏輯,在我們這個(gè)例子中我們也會(huì)出現(xiàn)這個(gè)問題。怎么解決呢?那么我們就可以將變化的部分抽象出來: 架構(gòu)設(shè)計(jì)的五大原則-SOLID ,后續(xù)如果還需要增加吃的方法那么只需要實(shí)現(xiàn)這個(gè)接口即可。

但是在這本書中,并沒有去強(qiáng)調(diào)將變化的部分抽象出來,其認(rèn)為修改是不可避免的,所以我們需要把控好修改的影響,所以提出了高層組件的修改不會(huì)影響底層組件,組件層次越低越穩(wěn)定。對(duì)于J2EE的開發(fā)者來說,三層開發(fā)肯定并不陌生,controller,service,dao:

如果我們修改controller那么service其實(shí)是無感知的,不會(huì)受影響,如果我們修改service,dao是不會(huì)受影響的,但是我們的controller是會(huì)受影響。所以越底層的組件那么其實(shí)應(yīng)該越穩(wěn)定。通過這種方式我們可以控制修改范圍的影響??偨Y(jié)起來就是通過將系統(tǒng)劃分為一系列組件,并且將這些組件間的依賴關(guān)系按層次結(jié)構(gòu)進(jìn)行組織,使得高階組件不會(huì)因低階組件被修改而受到影響。

5.LSP:里氏替換

任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。大多數(shù)人認(rèn)為L(zhǎng)SP其實(shí)就是指導(dǎo)如何使用繼承關(guān)系的一種方法,尤其是我們?cè)陂_發(fā)的過程中用spring依賴注入的基本都是基類而非具體的實(shí)現(xiàn)類,這個(gè)的確也是LSP的一種實(shí)現(xiàn)手段。LSP也在逐漸演變成一種更廣泛的,指導(dǎo)接口與其實(shí)現(xiàn)方式的設(shè)計(jì)原則。

這里用書中的一個(gè)反面例子來舉例,假如我們現(xiàn)在在構(gòu)建一個(gè)提供出租車調(diào)度服務(wù)的系統(tǒng),我們提供restful進(jìn)行調(diào)用,有這么一個(gè)司機(jī),如果我們想調(diào)度他那么需要訪問以下請(qǐng)求:

purplecab.com/driver/Bob/pickupAddress/24 Maple St./pickupTime/153/destination/ORD

每個(gè)公司想要接入我們的系統(tǒng)都得遵循上面的規(guī)矩,但是有一個(gè)公司Acme把destination寫成了縮寫dest,但是由于這個(gè)公司比較大,不想修改回來,所以調(diào)度系統(tǒng)只能寫如下的if邏輯:

if(driver.getDispatchUri().startsWith("acme.com"))

這種邏輯一般的軟件架構(gòu)師都不會(huì)允許這樣一條語句出現(xiàn)在系統(tǒng)中,如果又出現(xiàn)了一個(gè)公司違反了那么是否又需要增加一條if邏輯?軟件架構(gòu)師應(yīng)該創(chuàng)建一個(gè)調(diào)度請(qǐng)求創(chuàng)建組件,并讓該組件使用一個(gè)配置數(shù)據(jù)庫(kù)來保存URI組裝格式,如下:

URI 調(diào)度格式
Acme.com /pickupAddress/%s/pickupTime/%s/dest/%s
. * . /pickupAddress/%s/pickupTime/%s/destination/%s

但是這樣我們也需要增加一個(gè)組件來應(yīng)對(duì)這個(gè)情況,也增加了復(fù)雜性。

6.ISP:接口隔離原則

首先大家看看下面這個(gè)例子:

我們這里的User1,User2,User3都是依賴OPS的,但是User1只需要用op1,User2用op2,User3用op3。在這種情況下,雖然User1不會(huì)和op2,op3產(chǎn)生直接的調(diào)用關(guān)系,但在源代碼層次上也與他們形成依賴關(guān)系。這種依賴關(guān)系會(huì)導(dǎo)致兩個(gè)問題:
  • 修改op2,op3的邏輯會(huì)導(dǎo)致op1的邏輯變化

  • 就算邏輯不變化,修改op2也會(huì)導(dǎo)致重新編譯和部署User1。

我們通過下面這種方將不同的操作隔離成接口,運(yùn)用第5節(jié)的LSP,我們將OPS類實(shí)現(xiàn)這三個(gè)接口,然后替換在User1中的U1Ops,由于依賴的是最小接口所以就不會(huì)出現(xiàn)上面的問題。

架構(gòu)設(shè)計(jì)的五大原則-SOLID

在書中對(duì)于ISP強(qiáng)調(diào)得比較多,在后面也講了CRP原則,不要強(qiáng)迫一個(gè)組件的用戶依賴他們不需要的東西,CRP是ISP的一個(gè)普適版。ISP是針對(duì)類來說,CRP是針對(duì)組件來說。所以我們總結(jié)起來就是:

不要依賴不需要的東西

7.DIP: 依賴反轉(zhuǎn)

依賴反轉(zhuǎn)其實(shí)總結(jié)起來就是多依賴抽象,少依賴具體實(shí)現(xiàn)。但是事事并沒有那么絕對(duì),我們的String類是一個(gè)具體的實(shí)現(xiàn)類但是在我們的代碼中隨處可見,那是不是我們就違反了DIP了呢?其實(shí)不是的,我們String已經(jīng)非常穩(wěn)定了,就算修改也會(huì)被嚴(yán)格的控制,所以我們不需要擔(dān)心修改String類會(huì)發(fā)生一些意想不到的問題。所以對(duì)于我們穩(wěn)定的東西,其實(shí)DIP原則就不適用了,而我們需要重點(diǎn)關(guān)注的應(yīng)該經(jīng)常變動(dòng)的。這里我想要說的一點(diǎn)的是,大家在編碼過程中寫List的時(shí)候雖然大多數(shù)時(shí)候用的是ArrayList,但是其實(shí)很少寫下面這句話ArrayList list = new ArrayList(),更多的是寫List list = new ArrayList(),其實(shí)這個(gè)就是DIP的一個(gè)實(shí)現(xiàn)。

這里要說一下為什么叫反轉(zhuǎn)?有反轉(zhuǎn)就有正轉(zhuǎn),如下圖所示:

這里的我們的serviceImpl是service的具體實(shí)現(xiàn),在圖中我們的依賴流向沒有發(fā)生變化,所以叫正轉(zhuǎn)。我們采用DIP來進(jìn)行設(shè)計(jì):

可以看見我們這里的最后的流向放生了變化,所以可以叫他依賴反轉(zhuǎn)。

DIP還有幾個(gè)編碼規(guī)則需要注意:

  • 多使用抽象接口,盡量避免使用具體實(shí)現(xiàn)類。

  • 盡量不要在具體實(shí)現(xiàn)類上面創(chuàng)建子類。

  • 盡量不要覆蓋繼承的抽象類的方法:由于我們依賴的是抽象,有可能邏輯中已經(jīng)對(duì)這些方法產(chǎn)生了依賴,如果覆蓋有可能會(huì)造成問題。

8.總結(jié)

本文講了一下設(shè)計(jì)的五大原則SOLID,SOLID在這《架構(gòu)整潔之道》中一直貫穿,這五大原則能幫助我們?cè)谠O(shè)計(jì)的時(shí)候做出更多優(yōu)秀的架構(gòu)設(shè)計(jì),如果想了解更多的一些細(xì)節(jié)可以看看這本書。

如果你覺得這篇文章對(duì)你有文章,可以關(guān)注我的技術(shù)公眾號(hào),也可以加入我的技術(shù)交流群進(jìn)行更多的技術(shù)交流。你的關(guān)注和轉(zhuǎn)發(fā)是對(duì)我最大的支持,O(∩_∩)O。

架構(gòu)設(shè)計(jì)的五大原則-SOLID


分享標(biāo)題:架構(gòu)設(shè)計(jì)的五大原則-SOLID
當(dāng)前URL:http://weahome.cn/article/igjssg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部