設計模式六大原則——裏氏替換原則(LSP)
概述
裏氏替換原則(LSP,Liskov Substitution Principle)是關於繼承機製的原則,是實現開放封閉原則的具體規範,違反了裏氏替換原則必然違反了開放封閉原則。
引經據典
約瑟夫.斯大林,蘇聯時期蘇聯共產黨的最高領導人,對於斯大林有沒有替身?有幾個替身?有一種說法:斯大林有好幾個替身,最著名的當屬“第一替身”葉夫謝伊.盧比茨基——他“扮演”領袖斯大林長達15年之久,很多高官都被蒙在鼓裏。
斯大林作為一國的領導人,肯定要不停的參加各種的聚會,進行各中慰問。。。找幾個替身,忙裏偷閑或者外出打掩護......
子類必須完全實現父類的方法
替身代替斯大林去參加各種活動時,他的相貌和一舉一動都必須和真的斯大林一模一樣,畢竟斯大林代表的是一個國家,如果讓別人發現來見自己的是個替身,那不就讓人寒心了嘛... 看一下代碼:
//斯大林 public class SiDaLin { //斯大林講話行為 public virtual void SpeakWay() { Console .WriteLine ("右手舉過頭頂、伸出兩個手指、不斷前後擺動,以表示強調或憤慨。") } } //替身 public class TiShen : SiDaLin { //替身的講話行為 public override void SpeakWay() { Console .WriteLine ("右手舉過頭頂、伸出兩個手指、不斷前後擺動,以表示強調或憤慨。") } }
不知道大家有沒有注意到上麵代碼中父類中的virtual和子類中的override,為什麼要用到它們?
在繼承關係中,子類對父類的繼承除了字段、屬性,還有方法,而使同一方法在子類中表現出不同的行為是通過多態表現的,具體在語言上的操作上表現為父類提供虛函數,而在子類中覆寫該虛函數,這是抽象機製的重要基礎。
public static void DoSomething(Fatherclass f) { f.Method(); }
如果Method被實現為虛函數,並且在子類中被覆寫,那麼傳入DoSomething中的實參既可以是父類,也可以是子類,子類完全可以替代父類在此調用自己的方法,這正是裏氏替換原則強調的繼承關係,代碼如下:
class Fatherclass { //父類行為 public virtual void Method() { } } class Sonclass :Fatherclass { //子類重寫父類方法 public override void Method() { } }
(上麵這個問題的回答參考《你必須知道的.NET》)
子類可以有自己的“個性”
采用裏氏替換原則時,盡量避免子類的“個性”,一旦子類有“個性”,這個子類和父類之間的關係就很難調和了,把子類當做父類使用,子類的“個性”被抹殺——委屈了點;把子類單獨作為一個業務來使用,則會讓代碼間的耦合關係變得撲朔迷離——缺乏類替換的標準。
就拿斯大林的替身來說,每一個替身都是一個人,都有自己的“個性”,但是他們是斯大林的替身,那麼他們平時的表現就必須按照斯大林的表現來,如果他們加入自己的“個性”,那麼他們替身的身份就會漏出破綻。
結論
實現開閉原則的關鍵步驟是抽象化,父類與子類之間的繼承關係就是抽象化的體現,因此裏氏替換原則是實現開閉原則的具體步驟規範,違反裏氏替換原則一定違反開閉原則,反之未必。
最後更新:2017-04-03 08:26:15