首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

設計模式核心原則:里氏替換原則(LSP)深度解析與重構實戰

     編輯:關於C++

什麼是里氏替換原則?

里氏替換原則(Liskov Substitution Principle, LSP)由 Barbara Liskov 於 1987 年提出,核心定義:

若對每一個類型為 T₁ 的對象 o₁,都存在類型為 T₂ 的對象 o₂,使得以 T₁ 定義的所有程序 P 在所有對象 o₁ 都替換為 o₂ 時行為不變,則 T₂ 是 T₁ 的子類型。

通俗說:子類對象必須能無縫替換父類對象,且不改變程序的正確性。

違反 LSP 的典型案例

// 父類:減法計算器
class Calc {
    public void calc(int a, int b) {
        System.out.println(a + " - " + b + " = " + (a - b));
    }
}

// 子類:覆寫為加法 —— 破壞了父類行為契約
class CalcSon extends Calc {
    @Override
    public void calc(int a, int b) {
        System.out.println(a + " + " + b + " = " + (a + b)); // 行為改變!
    }
}

// 測試
Calc c = new Calc(); c.calc(10, 20);  // 輸出 10 - 20 = -10
Calc c2 = new CalcSon(); c2.calc(10, 20); // 輸出 10 + 20 = 30 —— 行為不一致!

這樣的繼承導致多態失效:父類引用指向子類對象時,語義發生根本改變,違背「is-a」關係。

LSP 的四大約束條件

  1. 子類不覆寫父類非抽象方法,只實現抽象方法或新增方法。
  2. 子類可新增獨有方法(如 addThem()),不影響父類協議。
  3. 參數逆變(Contravariance):子類方法參數類型應比父類更寬鬆(父類用 ArrayList,子類用 List)。
  4. 返回值協變(Covariance):子類返回類型應比父類更具體(父類返回 List,子類返回 ArrayList)。

重構策略:引入抽象基類

將原本的繼承關係解除,改為依賴/組合或共同繼承抽象介面:

// 抽象介面
public abstract class Calculator {
    public abstract void calc(int a, int b);
}

// 兩個獨立實現,互不干擾
public class SubCalc extends Calculator {  // 減法
    @Override public void calc(int a, int b) { ... }
}
public class AddCalc extends Calculator {  // 加法
    @Override public void calc(int a, int b) { ... }
    public void addThem(int a, int b) { ... } // 專有方法
}

重構後的優勢

  • 消除運行時行為突變風險
  • 符合「開閉原則」:新增運算類型只需新增實現類,不修改既有代碼
  • 單元測試更容易:每個實現類獨立驗證

實戰經驗總結

「繼承是強耦合,組合是弱耦合。只有真正滿足『is-a』且行為可替換時,才使用繼承;其餘情況優先考慮介面+組合。」

掌握 LSP 不僅能避免設計缺陷,更是寫出可維護、可擴展系統的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved