設計原則與思想 設計原則

2021-10-08 08:35:36 字數 3674 閱讀 7955

如何理解單一職責原則(srp) ?

solid原則並非單純的1個原則,而是由5個設計原則組成,他們分別是:單一職責原則,開閉原則,裡式替換原則,介面隔離原則和依賴反轉原則,依次對應solid中的s,o,l,i,d這五個英文本母

單一職責原則的英文是single responsibility principle 縮寫srp . 意思是乙個類或者模組只負責完成乙個職責(或者功能)

乙個類只負責完成乙個小職責或者功能.不要設計大而全的類,要設計粒度小,功能單一的類. 單一職責原則是為了實現**高內聚,低耦合,提高**的復用性,可讀性,可維護性.

如何判斷類的職責是否夠單一

不同的應用場景,不同階段的需求背景,不同的業務層面,對同乙個類的職責是否單一,可能會有不同的判斷結果.一些側面的判斷指標更具有直到意義和可執行性,比如,出現下面這些情況就有可能說明這類的設計不滿足單一職責原則:

類中的**行數,函式或者屬性過多.

類依賴的其他類過多,或者依賴類的過多.

私有方法過多;

比較難給類起乙個合適的名字;

類中大量的方法都是集中操作類中的某幾個屬性

類的職責是否涉及得越單一越好

單一職責原則通過避免設計大而全的類,避免將不相關的功能耦合在一起,來提高類的內聚性.同時,類職責單一,類依賴的和被依賴的其他類也會變少,減少了**的耦合性,以此來實現**的高內聚,低耦合.但是,如果拆的過細,實際上會適得其反,反倒會降低內聚性,也會影響**的可維護性

1.如何理解"對擴充套件開放,對修改關閉"?

新增乙個新的功能,應該是通過在已有的**基礎上擴充套件**(新增模組,類,方法屬性等),而非修改已有的**(修改模組,類,方法屬性等)的

方式來完成.關於定義,我們要注意兩點.第一點事,開閉原則並不是說完全杜絕修改,而是以最小的修改**的代價來完成新功能的開發.第二點是,統一的**改動,在粗**粒度下,可能被認定為"修改";在細**粒度下,可能又被認定為擴充套件.

2.如何做到"對擴充套件開發,修改關閉"

我們要時刻具備擴充套件意識,抽象,封裝意識.在寫**的時候,要多花點時間思考,這段**未來可能有哪些需求變更,如何設計**結果,事先留好擴充套件點,以便在未來變更的時候,在不改動**整體結構,做到最小**改動的情況下,將新的**靈活的插入到擴充套件點行

總結:對擴充套件開放是為了應對變化(需求),對修改關閉時為例保證已有**的穩定性;最終結果是為了讓系統更有彈性

lsp描述:

子類物件能夠替換程式中父類物件出現的任何地方,並且保證原來程式的邏輯行為不變及正確性不背破壞

哪些**明顯違背了lsp?

1.子類違背了父類宣告要實現的功能

例如:父類實現金額的排序是根據金額的大小,而子類是根據時間排序,那麼子類的設計就違背了裡式替換原則

2.子類違背了父類對輸入,輸出,異常的約定

在父類中,某個函式約定:執行出錯的時候返回 null;獲取資料為空的時候返回空集合(empty collection)。而子類過載函式之後,實現變了,執行出錯返回異常(exception),獲取不到資料返回 null。那子類的設計就違背裡式替換原則。

3.子類違背了父類注釋中所羅列的任何特殊說明

父類中定義的 withdraw() 提現函式的注釋是這麼寫的:「使用者的提現金額不得超過賬戶餘額……」,而子類重寫 withdraw() 函式之後,針對 vip 賬號實現了透支提現的功能,也就是提現金額可以大於賬戶餘額,那這個子類的設計也是不符合裡式替換原則的。

總結:個人理解裡式替換原則是子類完美繼承父類的設計初衷,並做了增強(下面是具體的)

裡式替換原則是用來指導,繼承關係中子類該如何設計的乙個原則。理解裡式替換原則,最核心的就是理解「design by contract,按照協議來設計」這幾個字。父類定義了函式的「約定」(或者叫協議),那子類可以改變函式的內部實現邏輯,但不能改變函式原有的「約定」。這裡的約定包括:函式宣告要實現的功能;對輸入、輸出、異常的約定;甚至包括注釋中所羅列的任何特殊說明。

理解這個原則,我們還要弄明白裡式替換原則跟多型的區別。雖然從定義描述和**實現上來看,多型和裡式替換有點類似,但它們關注的角度是不一樣的。多型是物件導向程式設計的一大特性,也是物件導向程式設計語言的一種語法。它是一種**實現的思路。而里式替換是一種設計原則,用來指導繼承關係中子類該如何設計,子類的設計要保證在替換父類的時候,不改變原有程式的邏輯及不破壞原有程式的正確性。

如何理解「介面隔離原則」?

客戶端不應該被強迫依賴它不需要的介面。其中的「客戶端」,可以理解為介面的呼叫者或者使用者.

如果把「介面」理解為一組介面集合,可以是某個微服務的介面,也可以是某個類庫的介面等。如果部分介面只被部分呼叫者使用,我們就需要將這部分介面隔離出來,單獨給這部分呼叫者使用,而不強迫其他呼叫者也依賴這部分不會被用到的介面。

如果把「介面」理解為單個 api 介面或函式,部分呼叫者只需要函式中的部分功能,那我們就需要把函式拆分成粒度更細的多個函式,讓呼叫者只依賴它需要的那個細粒度函式。

如果把「介面」理解為 oop 中的介面,也可以理解為物件導向程式設計語言中的介面語法。那介面的設計要盡量單一,不要讓介面的實現類和呼叫者,依賴不需要的介面函式。

2. 介面隔離原則與單一職責原則的區別

單一職責原則針對的是模組、類、介面的設計。介面隔離原則相對於單一職責原則,一方面更側重於介面的設計,另一方面它的思考角度也是不同的。介面隔離原則提供了一種判斷介面的職責是否單一的標準:通過呼叫者如何使用介面來間接地判定。如果呼叫者只使用部分介面或介面的部分功能,那介面的設計就不夠職責單一。

1. 控制反轉

實際上,控制反轉是乙個比較籠統的設計思想,並不是一種具體的實現方法,一般用來指導框架層面的設計。這裡所說的「控制」指的是對程式執行流程的控制,而「反轉」指的是在沒有使用框架之前,程式設計師自己控制整個程式的執行。在使用框架之後,整個程式的執行流程通過框架來控制。流程的控制權從程式設計師「反轉」給了框架。

2. 依賴注入

依賴注入和控制反轉恰恰相反,它是一種具體的編碼技巧。我們不通過 new 的方式在類內部建立依賴類的物件,而是將依賴的類物件在外部建立好之後,通過建構函式、函式引數等方式傳遞(或注入)給類來使用。

3. 依賴注入框架

我們通過依賴注入框架提供的擴充套件點,簡單配置一下所有需要的類及其類與類之間依賴關係,就可以實現由框架來自動建立物件、管理物件的生命週期、依賴注入等原本需要程式設計師來做的事情。

4. 依賴反轉原則

依賴反轉原則也叫作依賴倒置原則。這條原則跟控制反轉有點類似,主要用來指導框架層面的設計。高層模組不依賴低層模組,它們共同依賴同乙個抽象。抽象不要依賴具體實現細節,具體實現細節依賴抽象。

「基於介面而非實現程式設計」跟「依賴注入」,看起來非常類似,那它倆有什麼區別和聯絡呢?

「基於介面而非實現程式設計」與「依賴注入」的聯絡是二者都是從外部傳入依賴物件而不是在內部去new乙個出來。

區別是「基於介面而非實現程式設計」強調的是「介面」,強調依賴的物件是介面,而不是具體的實現類;而「依賴注入」不強調這個,類或介面都可以,只要是從外部傳入不是在內部new出來都可以稱為依賴注入。

待續…

物件導向思想設計原則

物件導向思想設計原則 物件導向思想設計原則 在實際的開發中,我們要想更深入的了解物件導向思想,就必須熟悉前人總結過的物件導向的思想的設計原則。單一職責原則 開閉原則 黎克特制替換原則 依賴注入原則 介面分離原則 迪公尺特原則 單一職責原則 其實就是開發人員經常說的 高內聚,低耦合 也就是說,每個類應...

設計原則 開閉原則

開閉原則的含義是對擴充套件開放,對修改關閉。意思就是在遇到新的需求或者變動的時候,提倡對原 擴充套件使其滿足新的需求,不提倡修改原 來達到目的。乙個專案不可能在開發完畢後就一成不變了,它總會有新的需求或者對老的需求進行更新。這樣就要盡可能的遵從設計原則中的開閉原則,這個原則告訴我們,要盡量避免對原 ...

設計原則 開閉原則

怎樣的 改動才能被定義為 擴充套件 怎樣的 改動才定義為 修改 怎樣才算滿足或者違反開閉原則?修改 意味著違反開閉原則嗎?開閉原則是最難理解,也是最難掌握,同時也是最有用的一條原則。這條原則並不是看幾篇文章,理解了其概念就能掌握和靈活應用的。要想深入理解,掌握這條原則,需要大量的實戰。開閉原則,英文...