設計原則學習小結

2021-07-03 12:57:54 字數 2543 閱讀 2358

日期:2023年4月14日 15:43 星期二 農曆 乙未 羊年 二月廿六

修改記錄:

正文:事物往往有其內在規律,遵循事物的內在規律有時往往能起到事半功倍的效果。物件導向的軟體設計也是這樣,要想設計出擴充套件性好,重用性高的軟體,也必須遵守一些它的一些基本原則。按照這些原則的首字母,我們可以簡稱為"solid"原則。

原則一:單一職責原則(single responsibility principle)

類或者函式只有乙個引起它變化的原因。

什麼是職責:職責就是指變化的原因。

我的思考:

(1)單一職責原則不符合物件導向的理解方式。例如說書中所舉的modem的例子,本身能夠很好的從官modem類來對映現實中真實的modem類,從職責上把它們分成兩個類反而不那麼好理解了。

自我解答:個人理解確實存在這個問題。不過這樣做能迫使開發人員能從職責的角度去把類進一步細分,也是乙個思考的過程,對實現來說是有好處的。

(2)modem類分成兩個類後,最終還是要合一。這樣不就永遠也有一些類無法滿足單一職責了嗎?

自我解答:最終對外暴露的肯定還是乙個modem類,但是經過細分以後,需求改變以後,modem類基本是穩定的。因為需求的改變一般只會改變會話管理與資料管理這兩個類中的乙個,並不會因此而改變modem類。所以對三個新的類來說,都實現了單一職責了。

原則二:開放封閉原則(open-closed principle)

類應該對擴充套件開放,對修改封閉。

我的思考:

(1)有些需求是無法通過擴充套件來實現,或者說通過擴充套件來實現的代價是非常大的,這樣如何做到開放封閉原則呢?

自我解答:個人理解確實存在這個問題,無論設計得多麼完美的軟體都可能存在這種問題,只是我們要盡量降低出現這種問題的可能性。用丁輝的話來說,就是:使得軟體的設計與需求變化的方向正交,這樣需求的變化就不會影響到已有的軟體設計了。但是一旦真有這種需求,應該通過進一步的重構來適應新的需求變化的方向。

(2)其實這個開放封閉原則與我們現在商用版本修改**的策略很類似:新增需求與修改故障盡量不影響現有架構與功能。最常用的辦法往往是在某些地方特殊處理一下即可,雖然按照開放封閉原則,我們現在的這種做法應該是修改而不是擴充套件,但是我們應該是用盡量少的修改來達到擴充套件的目的,應該算是一種特殊的擴充套件吧,至少目的上應該是一致的。在c語言的前提下,新增**100%的不修改原有**,在目前來說是很難的。但是我們現有的「打補丁」的方式真的好嗎?我不知道。但是至少日積月累以後,被後面的人罵的概率很大。那麼在現有的條件下,我們應該如何突破開放封閉原則這個魔咒呢?

原則三:黎克特制替換原則(liskov substitution principle)

所有父類物件出現的地方都應該可以用其子類物件替換而不會產生錯誤。

我的思考:

(1)黎克特制替換原則是否要求父類的所有的方法都是虛函式呢?如果不要求,那麼父類在呼叫那個非虛函式方法的時候,子類就不能替換,也就沒有遵循黎克特制替換原則了。我個人認為應該是的。

補充:經過向金華同學請教,金華認為黎克特制替換原則應該不要求父類所有的函式全都是需函式。當父類在呼叫某個非虛函式方法的時候,可以把子類的型別強轉成父類的型別然後去呼叫,這個時候能夠正常的執行,所以應該是符合黎克特制替換原則的。那麼新的問題來了,黎克特制替換原則是否要求在替換的時候子類型別都要強轉成父類型別呢?金華認為是的。

(2)通過上乙個問題,我們得到的結論是不要求父類的所有函式全都是虛函式。那麼當父類有乙個非虛函式,子類也有乙個同名的非虛函式時,這種情況是否滿足黎克特制替換原則呢?從表面上看,型別強轉成父類以後,子類的那個非虛函式永遠起不到作用,貌似滿足黎克特制替換原則,其實不然,因為替換後的執行結果的表現還是父類的,但是程式設計師的預期是子類的,與預期不一致,應該不符合黎克特制替換原則。

(3)我們經常講子類與父類的關係應該是is-a的關係,即子類應該是父類的乙個更具體的表示。但是並不是具有這樣關係的就是滿足黎克特制替換原則的,黎克特制替換原則必須同時滿足前置條件與後置條件。所謂前置條件與後置條件應該是在定義基類的時候就約定好的乙個契約。is-a關係通常只是乙個前置條件,後置條件通常是隱含的。例如正方形與長方形的例子,長方形是基類,它的乙個隱含的後置條件是修改長不影響寬,修改寬不影響長。如果正方形繼承了長方形,那它雖然滿足了前置條件,確不滿足後置條件。

原則四:介面分離原則(inte***ce segregation principle)

介面應該盡量小而明確,不應該強迫客戶依賴與他們不用的方法。

我的思考:

(1)我們產品**中的dbaccess介面是否是乙個胖介面?既然說介面應該盡量小而明確,那麼我們是否應該把它按照表來拆分成各個不同的介面呢?我個人認為它不是乙個胖介面,因為各個表的行為都是增、刪、改,對客戶端來說只是表名不同而已,dbaccess應該是乙個很好的抽象,它並不會造成各個客戶端之間的耦合,所以我理解它應該不是乙個胖介面。真正的胖介面應該是讓某些客戶端看到了一些它不需要的東西。

原則五:依賴倒置原則(dependency inversion principle)

高層模組不應該依賴與底層模組,二者都應該依賴於抽象。具體依賴於抽象,抽象不依賴於具體。

我的思考:

(1)依賴於抽象,抽象是什麼?其實抽象就是一堆介面的集合。這個原則應該是所有的設計原則中最容易理解的乙個原則,也是最符合我們在實際專案中用得最普遍的乙個原則。就是讓我們基於介面程式設計。這就要求我們的介面要設計得盡量的穩定。

六大設計原則小結

一 單一職責原則 乙個類負責乙個功能,如果乙個類t負責負責職責a 職責b,這時如果因為職責a的需求改變需要修改類t時,可能會影響到職責b功能發生變化 二 黎克特制替換原則 子類可以擴充套件父類的功能,但不能改變父類原有的功能。三 依賴倒置原則 高層模組不應該依賴底層模組,二者都應該依賴其抽象 抽象不...

設計模式學習 設計原則

單一職責原則 就乙個類而言,應該僅有乙個引起他變化的原因 如果乙個類承擔的職責過多,就等於把這些職責耦合在一起,乙個職責的變化可能會削弱或者抑制這個類完成其他職責的能來,這種耦合會導致脆弱的設計,當變化發生時,設計會遭受意想不到的破壞 如果你能想到多於乙個的動機去改變乙個類,那麼這個類就具有多餘乙個...

設計原則之美學習筆記 設計原則

乙個類只負責完成乙個職責或者功能。不要設計大而全的類,要設計粒度小 功能單一的類。單一職責原則是為了實現 高內聚 低耦合,提高 的復用性 可讀性 可維護性。不同的應用場景 不同階段的需求背景 不同的業務層面,對同乙個類的職責是否單一,可能會有不同的判定結果。實際上,一些側面的判斷指標更具有指導意義和...