java設計模式學習筆記——里氏替換原則

oo中的繼承性的思考和說明

一、繼承包含這樣一層含義:父類中凡是已經實現好的方法,其實是在設定規範和契約,雖然它不強制要求全部的子類必須遵循這些七月,可是若是子類對這些已經實現的方法任意修改,就會對整個繼承體系形成破壞。
二、繼承在給程序設計帶來便利的同時,也帶來了弊端。好比使用繼承會給程序帶來侵入性,程序的可移植性下降,增長對象間的耦合性,若是一個類被其餘的類所繼承,則當這個類須要修改時,必須考慮到全部的子類,而且父類修改後,全部涉及到子類的功能都有可能產生故障。
三、問題提出:在編程中,如何正確的使用繼承? 答:儘量遵循里氏替換原則。編程

基本介紹

一、里氏替換原則在1988年,由麻省理工學院的一位姓裏的女士提出的。
二、若是對每一個類型爲T1的對象o1,都有類型爲T2的對象o2,使得T1定義的全部程序p在全部的對象o1都代換成o2是,程序p的行爲沒有發生變化,那麼類型T2是類型T1的子類型。換句話說,全部,全部應用類型的地方必須能透明地使用其子類的對象。
三、在使用繼承時,遵循里氏替換原則,在子類中儘可能不要重寫父類的方法。
四、里氏替換原則告訴咱們,繼承實際上讓兩個類耦合性加強了,在適當的狀況下,能夠經過聚合,組合,依賴來解決問題this

應用案例

沒有使用里氏替換原則

public class Liskov {
    public static void main(String[] args) {
        A a = new A();
        System.out.println("1-8=" + a.func1(1, 8));

        System.out.println("--------------------");
        B b = new B();
        System.out.println("11-3=" + b.func1(11, 3));
        System.out.println("1-8=" + b.func1(1, 8));
        System.out.println("11+3+9=" + b.func3(11, 3));
    }
}

class A {
    // 兩個數的差
    public int func1(int num1, int num2) {
        return num1 - num2;
    }

    // 兩個數的積
    public int funcBase(int num1, int num2) {
        return num1 * num2;
    }
}

//B類繼承了A
//增長了一個新功能,完成兩個數相加,而後和9求和
class B extends A {
    // 這裏,重寫了A的方法,多是無心識
    public int func1(int a, int b) {
        return a + b;
    }

    public int func3(int a, int b) {
        return func1(a, b) + 9;
    }
}

使用里氏替換原則

public class Liskov {
    public static void main(String[] args) {
        A a = new A();
        System.out.println("1-8=" + a.func1(1, 8));

        System.out.println("--------------------");
        B b = new B();
        System.out.println("11-3=" + b.func1(11, 3));
        System.out.println("1-8=" + b.func1(1, 8));
        System.out.println("11+3+9=" + b.func2(11, 3));

        // 使用組合來使用A的相關方法
        System.out.println("--------------------");
        System.out.println("11-3=" + b.func3(11, 3));
        System.out.println("1-8=" + b.func3(1, 8));
        System.out.println("11+3+9=" + b.func2(11, 3));
    }
}

class Base {
    // 把更加基礎的方法和成員寫到Base類
    // 兩個數的積
    public int funcBase(int num1, int num2) {
        return num1*num2;
    }
}

class A extends Base {
    // 兩個數的差
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}

//B類繼承了A
//增長了一個新功能,完成兩個數相加,而後和9求和
class B extends Base {
    // 若是B須要使用A類得方法,使用組合關係
    private A a = new A();

    // 這裏,重寫了A的方法,多是無心識
    public int func1(int a, int b) {
        return a + b;
    }

    public int func2(int a, int b) {
        return func1(a, b) + 9;
    }

    // 使用A得方法
    public int func3(int a, int b) {
        return this.a.func1(a, b);
    }
}

上面這段代碼中,使用了里氏替換原則,將更基礎的方法funcBase()提取出來,而後將A類和B類繼承這個更基礎的Base類,採用依賴、聚合或耦合的方式來減小父類和子類的耦合

相關文章
相關標籤/搜索