三 :LSP(里氏代換原則)

hkmexu發表於2009-03-11

Liskov Substitution Principle , LSP

*******************************************************************************************

表述:

1.         如果每一個型別為T1的物件o1,都有型別為T2的物件o2,使得以T1定義的所有程式P在所有的物件o1都代換為o2,程式P的行為沒有變化,那麼型別T2是型別T1的子型別。

2.         換言之,一個軟體實體如果使用的是一個基類的話,那麼一定適用於其子類,而且它根本不能察覺出基類物件和子類物件的區別。只有衍生類替換基類的同時軟體實體的功能沒有發生變化,基類才能真正被複用。

3.         里氏代換原則由Barbar Liskov(芭芭拉.里氏)提出,是繼承複用的基石。

4.         一個繼承是否符合里氏代換原則,可以判斷該繼承是否合理(是否隱藏有缺陷)。

 

理解:

(1)   應當儘量從抽象類繼承,而不從具體類繼承。

一般而言,如果有兩個具體類AB有繼承關係,那麼一個最簡單的修改方案是建立一個抽象類C,然後讓類AB成為抽象類C的子類。即如果有一個由繼承關係形成的等級結構的話,那麼在等級結構的樹形圖上面所有的樹葉節點都應當是具體類,而所有的樹枝節點都應當是抽象類或者介面。

 

 

 

總結:

1.     為了保持LSP,所有子類必須符合使用基類的client所期望的行為。

2.     一個子型別不得具有比基型別(base type)更多的限制,可能這對於基型別來說是合法的,但是可能會因為違背子型別的其中一個額外限制,從而違背了LSP

3.     LSP保證一個子類總是能夠被用在其基類可以出現的地方!

 

 

備註 :

   

LSP講的是基類和子類的關係。只有當這種關係存在時,里氏代換關係才存在。如果兩個具體的類AB之間的關係違反了LSP的設計,(假設是從BA的繼承關係)那麼根據具體的情況可以在下面的兩種重構方案中選擇一種。 建立一個新的抽象類C,作為兩個具體類的超類,將AB的共同行為移動到C中來解決問題。 BA的繼承關係改為委派關係。

    在進行設計的時候,我們儘量從抽象類繼承,而不是從具體類繼承。如果從繼承等級樹來看,所有葉子節點應當是具體類,而所有的樹枝節點應當是抽象類或者介面。當然這個只是一個一般性的指導原則,使用的時候還要具體情況具體分析。

 

 

 

舉例:

Composite模式,Proxy模式,Strategy模式

 

相關文章