面向?qū)ο笤瓌t之里氏替換原則

一.簡稱

英文全稱是Liskov Substitution Principle, 縮寫是LSP

二.定義

如果對每一個類型為S的對象O1,都有類型為T的對象O2,使得以T定義的所有程序P在所有的對象O1都替換成O2時,程序P的行為沒有發(fā)生變化,那么類型S是類型T的子類型。
簡單的說就是所有引用基類的地方必須能透明地使用其子類的對象。通俗點講,只要父類能出現(xiàn)的地方子類就可以出現(xiàn),而且替換為子類也不會產(chǎn)生任何錯誤或異常,使用者根本就不需要知道是父類還是子類,但是反過來就不行,有子類出現(xiàn)的地方,父類未必就能適應(yīng)??偟膩碚f就是抽象。

比如從Window和View的關(guān)系來看

window.png
//窗口類
public class Window{
  public void show(View child){
    child.draw();
  }
}
//測量視圖的寬高為公用代碼,繪制實現(xiàn)交給具體的子類
public abstract class View{
  public abstract void draw();
  public void measure(int width,int height){
          //測量視圖大小
  }
}
//TextView 的具體實現(xiàn)
public class TextView extends View{
   public void draw(){


   }
}
//Button的具體實現(xiàn)
public class Button extends View{
   public void draw(){

  }
}

Window依賴于View,而View定義了一個視圖抽象,measure是各個子類共享的方法,子類覆寫View的draw方法實現(xiàn)自己特有的功能,任何繼承自View類的子類都可以設(shè)置給View方法,就是所說的里氏替換。通過里氏替換,就可以定義各式各樣的View,然后傳遞給Window,Window負責將View顯示到屏幕上。

三.核心原理

核心是抽象,而抽象又依賴于繼承特性。
繼承的優(yōu)缺點:
優(yōu)點:
(1)代碼復(fù)用,減少創(chuàng)建類的成本,每個子類都擁有父類的方法和屬性
(2)子類和父類基本相似,但又與父類有所區(qū)別
(3)提高代碼的可擴展性
缺點:
(1)只要繼承就必須擁有父類的所有屬性和方法
(2)可能造成子類代碼冗余、靈活度降低,因為子類必須擁有父類的屬性和方法。
在實際使用中要根據(jù)具體的情況來看要不要使用繼承。

四.注意事項

(1)子類的所有方法必須在父類中聲明,或子類必須實現(xiàn)父類中聲明的所有方法。因為根據(jù)里氏替換原則,為了保證系統(tǒng)的擴展性,在程序中通常使用父類來進行定義,如果一個方法只存在子類中,在父類中不提供相應(yīng)的聲明,則無法在以父類定義的對象中使用該方法。
(2)盡量把父類設(shè)計為抽象類或接口,讓子類繼承父類或?qū)崿F(xiàn)父接口,并實現(xiàn)父類中聲明的方法,運行時,子類實例替換父類實例,我們可以很方便地擴展系統(tǒng)的功能,同時無須修改原有子類的代碼,增加新的功能可以通過增加一個新的子類來實現(xiàn)。里氏替換原則是開閉原則的具體實現(xiàn)手段之一。

總結(jié)

里氏替換原則和開閉原則一般都是一起使用的,通過里氏替換來達到對擴展開放,對修改關(guān)閉的效果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容