软件设计原则(三)里氏替换原则 -Liskov Substitution Principle
里氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。 LSP是繼承復用的基石,只有當衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。
LSP講的是基類和子類的關系。只有當這種關系存在時,里氏代換關系才存在。如果兩個具體的類A,B之間的關系違反了LSP的設計,(假設是從B到A的繼承關系)那么根據具體的情況可以在下面的兩種重構方案中選擇一種。
-----創建一個新的抽象類C,作為兩個具體類的超類,將A,B的共同行為移動到C中來解決問題。
-----從B到A的繼承關系改為委派關系。
LSP,Liskov Substitution Principle:
1) If for each object?s?of type?S, there is an objectt?of type?T?such that for all programs P defined in terms of T, the behavior of P is unchanged when?s?is substituted fort?when S is a subtype of?T.
2) Functions that use pointers or references to base classes must be able to user objects of derived classes without knowing it.
所有引用基類的地方,都能透明地替換成其子類對象。只要父類能出現的地方,子類就可以出現。
引入里氏替換原則能充分發揮繼承的優點、減少繼承的弊端。
繼承的優點:
- 代碼共享,減少創建類的工作量;每個子類都有父類的方法和屬性;
- 提高代碼重用性;
- 子類可以形似父類,但又異于父類;
- 提高代碼可擴展性;
- 提高產品開放性。
繼承的缺點:
- 繼承是侵入性的——只要繼承,就必須擁有父類的屬性和方法;
- 降低代碼的靈活性——子類必須擁有父類的屬性和方法,讓子類自由的世界多了些約束;
- 增強了耦合性——當父類的屬性和方法被修改時,必須要考慮子類的修改。
示例(繼承的缺點):
??????? 原有類A,實現減法功能:
??????? 新增需求:新增兩數相加、然后再與100求和的功能,由類B來負責
OOPS! 原本運行正常的相減功能發生了錯誤。原因就是類B在給方法起名時無意中重寫了父類的方法!
問題由來:
??????? 有一功能P1,由類A完成。現需要將功能P1進行擴展,擴展后的功能為P,其中P由原有功能P1與新功能P2組成。新功能P由類A的子類B來完成,則子類B在完成新功能P2的同時,有可能會導致原有功能P1發生故障。
解決方案:
??????? LSP為繼承定義了一個規范,包括四層含義:
????????1)子類必須完全實現父類的方法
??????? 如果子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生畸變;則建議不要用繼承,而采用依賴、聚集、組合等關系代替繼承。
??????? 例如:父類AbstractGun有shoot()方法,其子類ToyGun不能完整實現父類的方法(玩具槍不能射擊,ToyGun.shoot()中沒有任何處理邏輯),則應該斷開繼承關系,另外建一個AbstractToy父類。
????????2)子類可以有自己得個性
??????? 即,在子類出現的地方,父類未必就能替代。
??????? 3)重載或實現父類方法時,輸入參數可以被放大(入參可以更寬松)
??????? 否則,用子類替換父類后,會變成執行子類重載后的方法,而該方法可能“歪曲”父類的意圖,可能引起業務邏輯混亂。
??????? 4)重寫或實現父類方法時,返回類型可以被縮小(返回類型更嚴格)
??????? 在實際編程中,我們常常會通過重寫父類的方法來完成新的功能,這樣寫起來雖然簡單,但是整個繼承體系的可復用性會比較差,特別是運用多態比較頻繁時,程序運行出錯的幾率非常大。
??????? 父類中凡是已經實現好的方法(相對于抽象方法而言),實際上是在設定一系列的規范和契約,雖然它不強制要求所有的子類必須遵從這些契約,但是如果子類對這些非抽象方法任意修改,就會對整個繼承體系造成破壞。而里氏替換原則就是表達了這一層含義。
??????? 里氏替換原則通俗的來講就是:子類可以擴展父類的功能,但不能改變父類原有的功能。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的软件设计原则(三)里氏替换原则 -Liskov Substitution Principle的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件设计原则(二)单一职责原则 -Sin
- 下一篇: 软件设计原则(四)依赖倒置原则 -Dep