這個原則看起來很簡單,就是說乙個類只能承擔乙個職責。
但這裡有乙個關鍵:「職責」是如何理解的?
按照漢語的理解,職責其實分為兩部分:「職」和「責」。「職」就是這個類是什麼,而「責」就是這個類要幹什麼。
舉個例子來說:door是乙個物件,那麼它的「職」就是門,「責」就是「開門、關門」等;而lock的「職」就是鎖,「責」就是「上鎖、開鎖」。如果設計的時候door同時具有鎖的職責,那麼door就違反了srp原則。
相信這是大家見得最多的原則,而且很多人都是這麼解釋的「對擴充套件開放、對修改封閉」,更加有人總結為「不修改**增加新的功能」!
太神奇了,不修改**增加新的功能!但我不免疑惑:不修改**怎麼增加新的功能呢?難道**會像生物一樣,基因變異?
仔細研究過後才發現,原來是這些總結的人誤導了我,根本不是什麼「不修改**增加新的功能」,也不是那個省略了主語的「對擴充套件開放,對修改封閉」,而是「被呼叫者開放擴充套件,呼叫者封閉修改」
還是舉門的例子:door物件是被其它物件例如人people呼叫,那麼door就是被呼叫者,people就是呼叫者。door物件可以擴充套件為「防盜門」、「防火門」、「逃生門」等,但people在呼叫的時候不需要關注具體是什麼門,只需要呼叫這些門公共的「開門、關門」等操作即可。
這個看起來是比較難理解的原則,但我可以給乙個很容易理解的總結:「子類的輸入不能比父類多,子類的輸出不能比父類少!」。
「輸入」就是指呼叫類的時候要給出的條件,最常見的就是函式引數,而一般的語言都可以從語法上保證這種子類和父類相同函式的引數必須相同;還有另外一種隱性的條件即「假設」或者「要求」也必須相同。
舉個簡單的例子:長方形和正方形。按照數學的定義,正方形是特殊的長方形。依照此定義看起來好像可以將正方形定義為長方形的子類,但實際上在物件導向設計中則是不行的,因為按照設定長方形長寬的方法不能來設定正方形的邊長,正方形要求長寬必須相等,而長方形沒有此「要求」。這就是子類的「假設」或者「假設」多於父類,違反了lsp原則。
「輸出」就是指呼叫類後返回的結果。即:子類的返回結果要包含父類的返回結果,可以多但絕對不能少。
為什麼設計時要滿足lsp原則呢?其實很簡單,因為呼叫者看到的只有父類,它根本不知道到底是哪個子類,呼叫者所有的處理都是基於父類提供給呼叫者的資訊(包括輸入資訊和輸出資訊)。
這個原則看起來有點嚇人,換個簡單的說法你就明白了,其實它就對應於《設計模式》開頭提到的兩個原則中的乙個:「基於介面程式設計,而不是基於實現程式設計」。(另外乙個是什麼呢?)
這裡的「程式設計」包括「呼叫者」和「被呼叫者」的程式設計。「呼叫者」基於介面進行呼叫,「被呼叫者」基於介面進行具體實現。
注意:和「依賴反轉」類似的兩個比較容易混淆的概念是「依賴注入」和「控制反轉」,詳細可以參考如下博文:
這個原則也很簡單,就是說乙個物件不要提供多個介面,不同的介面應該分離到不同的物件上去。
雖然大師的水平不容懷疑,但這裡我還是要懷疑一下:srp和isp本質上應該是乙個原則,只是說法不一樣而已。
為什麼這麼說呢?大家可以看看srp原則,它說的是「單一職責」。那麼職責最終體現在物件上是什麼呢?對,不就是介面麼!也就是說,如果遵循了srp原則,介面自然就隔離了。
物件導向設計原則
oo原則 封裝變化 多用組合,少用繼承 針對介面程式設計,不針對實現程式設計 為互動物件之間的松耦合而努力 類應該對擴充套件開放,對修改關閉 依賴抽象,不要依賴具體類 只和朋友交談 別找我,我會找你 類應該只有乙個改變的理由 從設計原則到設計模式 針對介面程式設計,而不是針對實現程式設計 客戶無需知...
物件導向設計原則
物件設計原則 物件導向設計原則 物件導向設計的基石是 開 閉 原則。開一閉 原則講的是 乙個軟體實體應當對擴充套件開放,對修改關閉。這個規則說的是,在設計乙個模組的時候,應當使這個模組可以在不被修改的前提下被擴充套件。從另外乙個角度講,就是所謂的 對可變性封裝原則 對可變性封裝原則 意味著兩點 1 ...
物件導向設計原則
oo原則 封裝變化 多用組合,少用繼承 針對介面程式設計,不針對實現程式設計 為互動物件之間的松耦合而努力 類應該對擴充套件開放,對修改關閉 依賴抽象,不要依賴具體類 只和朋友交談 別找我,我會找你 類應該只有乙個改變的理由 從設計原則到設計模式 針對介面程式設計,而不是針對實現程式設計 客戶無需知...