面向對象六大原則(三):里氏替換原則

一、概述

里氏替換原則(Liskov Substitution Principle ,縮寫:LSP),原則說任何基類可以出現的地方,子類一定可以出現。LSP是繼承複用的基石,只有當衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被複用,而衍生類也能在基類的基礎上增加新的行爲。

二、核心原理

里氏替換原則的核心原理是抽象,抽象又依賴於繼承這個特性,在OOP中,繼承的優缺點相當明顯,主要有以下幾點

優點:1.代碼重用,減少創建類的成本,每個子類都擁有父類的方法和屬性;2.子類與父類基本相似,但又與父類有所區別;3.提高代碼的可擴展性。

缺點:1.繼承是侵入性的,只要繼承就必須擁有父類的所有屬性和方法;2.可能造成子類代碼冗餘、靈活性降低,因爲子類必須擁有父類的屬性和方法。

三、實現方法

下面引用《Android源碼設計模式解析與實戰》一書中簡單示例:
//窗口類
    public class Window{
        public void show(View child){
            child.draw();
        }
    }

    //建立視圖抽象,測量視圖的寬高爲公用代碼,繪製實現交給具體的子類
    public abstract class View{
        public abstract void draw();
        public void measure(int width, int height){
            //測量視圖大小
        }
    }

    //Button的具體實現
    public class Button extends View{
        @Override
        public void draw() {
            //繪製按鈕
        }
    }

    //TextView的具體實現
    public class TextView extends View{
        @Override
        public void draw() {
            //繪製文本
        }
    }

上述示例中,Window依賴於View,而View定義了一個視圖抽象,measure是各個子類共享的方法,子類通過複寫View的draw方法實現具有各自特色的功能,在這裏,這個功能就是繪製自身的內容。任何繼承自View類的子類都可以設置給show方法,也就是所說的里氏替換。通過里氏替換,就可以自定義各式各樣、千變萬化的View,然後傳遞給Window,Window負責組織View,並且將View顯示在屏幕上。

上一篇博客 “面向對象六大原則(二):開閉原則” 中的示例也很好地反應了里氏替換原則,即MemoryCache、DiskCache、DoubleCache都可以替換ImageCache的工作,並且能夠保證行爲的正確性。ImageCache建立了獲取緩存圖片、保存緩存圖片的接口規範,MemoryCache等根據接口規範實現了相應的功能,用戶只需要在使用時指定具體的緩存對象就可以動態地替換ImageLoader中的緩存策略。這就使得ImageLoader的緩存系統具有了無限的可能性,也就是保證了可擴展性。

四、分析

里氏替換原則就是建立抽象,通過抽象建立規範,具體的實現在運行時替換掉抽象,保證系統的擴展性、靈活性。

開閉原則與里氏原則往往是生死相依、不離不棄,通過里氏替換來達到對擴展開放,對修改關閉的效果。然而,這兩個原則都同時強調了一個OOP的重要特性——抽象,因此,在開發過程中運用抽象是走向代碼優化的重要一步。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章