首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

合成復用原則(CARP)通俗解讀:組合/聚合優於繼承的實戰案例

     編輯:程式設計疑難解答

原則定義

盡量使用 **組合/聚合**(Has-a)關系復用代碼,而非**繼承**(Is-a)。新對象持有舊對象引用,通過委派調用舊對象方法實現功能擴展。

核心對比

繼承復用組合復用
靜態、編譯期確定動態、運行期可替換
破壞封裝(父類細節暴露給子類)保持封裝(只依賴接口)
父類變更強制子類變更低耦合,易維護
「白箱」復用「黑箱」復用

經典案例:策略模式

// 策略接口
interface PayStrategy { void pay(double amount); }

// 具體策略
class Alipay implements PayStrategy { public void pay(double a) { ... } }
class WechatPay implements PayStrategy { public void pay(double a) { ... } }

// 上下文(組合策略)
class Order {
    private PayStrategy strategy; // 組合
    public void setStrategy(PayStrategy s) { this.strategy = s; }
    public void checkout(double amt) { strategy.pay(amt); }
}

// 使用
Order order = new Order();
order.setStrategy(new Alipay()); // 運行期切換
order.checkout(99.9);

`Order` **不繼承** `PayStrategy`,而是**組合**它,運行時動態切換支付方式,完美體現合成復用。

其他案例

  • 代理模式:`Proxy` 組合 `RealSubject`,委派調用並添加預處理/后處理。
  • 裝飾器模式:`Decorator` 組合 `Component`,遞歸包裝增強功能。
  • Java 集合框架:`Collections.unmodifiableList(list)` 組合原列表提供只讀視圖,而非繼承 `ArrayList`。

何時仍用繼承

  • 真正的「Is-a」關系(`Dog` 是 `Animal`)。
  • 需要復用**受保護成員/方法**且子類不破壞父類不變式。
  • 模板方法模式骨架固定、子類填充細節。

總結

「有沒有」比「是不是」更靈活。設計時首問:「能不能用組合?」能則組合,不能再考慮繼承。

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