軟體設計原則 LisKov替換原則(LSP)

2021-05-28 12:02:24 字數 2555 閱讀 8923

「乙個軟體實體如果使用的是乙個基類的話,一定適用於其子類,而且根本不能覺察出基類物件和子類物件的區別。」

陳述:

barbara liskov對原則的陳述:

若對每個型別s的物件o1,都存在乙個型別t的物件o2,使得在所有針對t編寫的程式p中,用o1替換o2後,程式p的行為功能不變,則s是t的子型別。

通俗地講,就是

子型別能夠完全替換父型別,而不會讓呼叫父型別的客戶程式從行為上有任何改變。

意義:

我們在客戶程式在呼叫某乙個類時,實際上是對該類的整個繼承體系設定了一套約束,繼承體系中的所有類必須遵循這一約束,即

前置條件和後置條件必須保持一致

。這為物件繼承加上了一把嚴格的枷鎖。顯然,lsp原則對於約束繼承的氾濫具有重要意義。

分析:

例如:基類base,派生類derived,派生類例項d,函式f(base* p);

顯然d對於f是脆弱的。

經典例子:長方形與正方形駁論

class rectangle

long getwidth()

void setheight(long height)

long getheight()

};//正方形類

class square

long getside()

};

//正方形類(如果繼承自長方形類):

class square : public rectangle

long getwidth()

void setheight(long height)

long getheight()

long getside()

void setside(long side)

};

class smarttest}};

從上面小函式可見,只想改變長方形的寬時,如果把正方形看成一種長方形的話,則正方形的長和寬都被改變了。lsp原則被破壞了,square不應成為rectangle的子類。

結論:

黎克特制代換與通常的數學法則和生活常識有不可混淆的區別。

考慮乙個設計是否恰當時,不能孤立的看待並判斷,應該從此設計的使用者所作出的假設來審視它!

思考:

這個看似明顯正確的模型怎麼會出錯呢?

「正方形是一種長方形」

對不是smarttest函式的編寫者而言,正方形可以是長方形,但是對smarttest函式的編寫者而言,square絕對不是rectangle!!

ood中物件之間是否存在is-a關係,應該從行為的角度來看待。

->而行為可以依賴客戶程式做出合理的假設。

改進:

引入乙個quadrangle(四邊形)類,並將rectangle 與square變成它的具體子類,解決了rectangle 與square的關係不符合黎克特制替換原則的問題。

class quadrangle

;

quadrangle類只宣告兩個取值方法,不宣告任何的賦值方法。

//長方形類:

class rectangle : public quadrangle 

long getwidth()

void setheight(long height)

long getheight()

};

//正方形類:

class square : public quadrangle 

long getside()

long getwidth()

long getheight()

};

問題如何得以避免?基類quadrangle類沒有賦值方法,因此類似於 smarttest的resize()方法不可能適用於quadrangle型別,而只能適用於不同的具體子類rectangle 和square,因此黎克特制替換原則不可能被破壞。

結論:

相應設計模式:

參考資源:

《設計模式:可復用物件導向軟體的基礎》,erich gamma richard helm ralph johnson john vlissides著作,李英軍 馬曉星 蔡敏 劉建中譯,機械工業出版社,2005.6

《敏捷軟體開發:原則、模式與實踐》,robert c. martin著,鄧輝譯,清華大學出版社,2003.9

《設計模式解析》,alan shalloway等著(徐言聲譯),人民郵電出版社,2006.10

Liskov替換原則

2.3.3 liskov替換原則 barbara liskov於1988年提出了著名的替換原則 如果對於型別s的每個物件o1存在型別t的物件o2,那麼對於所有定義了t的程式p來說,當用o1替換 o2並且s是t的子型別時,p的行為不會改變。通俗地講,就是子型別能夠完全替換父型別,而不會讓呼叫父型別的客...

軟體設計原則 黎克特制替換原則

liskov substitution principle 黎克特制替換原則 定義 如果對每一型別為t1的物件o1,都有型別為t2的物件o2,使得以t1定義的所有程式p在所有的物件o1都替換成o2時,程式p的行為沒有發生變化,那麼型別t2是型別t1的子型別。擴充套件 乙個軟體實體如果適用乙個父類的話...

Liskov替換原則(LSP)

注 摘自 敏捷軟體開發 原則 模式與實踐 robert c.martin 對於lsp可以做如下解釋 子型別 subtype 必須能夠替換掉它們的基型別 base type barbara liskov首次寫下這個原則是在1988年。她說到,這裡需要如下替換性質 若對每個型別s的物件o1,都存在乙個型...