閱讀915 返回首頁    go 阿裏雲 go 技術社區[雲棲]


設計模式六大原則——裏氏替換原則(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

  上一篇:go SQL Server 中讀取當前年月
  下一篇:go 請教如何實現SQL查詢24小時內,當前時間之前20分鍾的信息