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

敏捷開發核心技巧:慎用繼承,善用組合與代理

     編輯:Java 相關知識

案例一:繼承帶來的隱性 Bug

會議管理系統中 ParticipantsInDB extends DBTable。DBTable 提供 clear()、getCount()。ParticipantsInDB 覆寫 countParticipants() 只統計未刪除記錄,但繼承了 getCount()(統計所有記錄)。

客戶端呼叫 partsInDB.getCount() 期望得到有效參會者數,實際得到總記錄數——繼承了不適用的行為。

根因分析:是否真正存在「是一種」關係?

  • ParticipantsInDB 代表業務領域的參會者集合,可跨多資料庫。
  • DBTable 僅代表單一資料表。
  • 兩者無繼承關係,應採用代理:ParticipantsInDB 持有 DBTable 實例,僅暴露所需方法(如 clear()),隱藏 getCount()。
public class ParticipantsInDB {
    private DBTable table = new DBTable("participants");
    public void clear() { table.clear(); } // 代理
    public int countParticipants() { /* 自有邏輯 */ }
}

優點:精確控制公開介面,避免繼承帶來的「契約污染」。

案例二:基類包含非通用功能

Component 含 width/height/setWidth/setHeight。Button (矩形) 需要,但 ClockComponent (圓形) 不需要卻被迫繼承。

解決方案:抽取共性,向下歸置

方案 A:引入中間類 RectangularComponent extends Component,Button 繼承它,ClockComponent 直接繼承 Component。

方案 B:提取 RectangularDimension 類,Button 組合並代理之。

核心原則:若基類功能非所有子類共享,則基類設計有缺陷,須重構。

總結:繼承決策檢查清單

  1. 子類是否會繼承不需要的功能?
  2. 若是,兩者是否真正存在「是一種」關係(里氏替換原則 LSP)?
  3. 無真繼承關係 → 採用代理/組合。
  4. 有真繼承關係 → 將非通用功能下移至具體子類或提取為獨立類供組合。

LSP:子類型必須能替換其基類型。盡量避免覆寫——覆寫往往是設計缺陷的徵兆。

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