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

代碼復用核心原則:面向接口編程、組合優於繼承、Bridge/Strategy 模式實戰

     編輯:Java 程式設計入門

前言:復用的本質是「變化點封裝」

代碼復用不是複製粘貼,而是識別變化維度,將其封裝為可替換的抽象。本文總結三大核心原則,並通過「文檔多格式輸出」案例對比繼承與組合架構。

原則一:面向接口編程 — 依賴抽象而非具體

  • 定義:對於完成相同功能的組件族,抽象出 interface 或 abstract class,客戶代碼僅依賴抽象類型。
  • 效果:替換實現零修改客戶代碼(OCP 開閉原則);支援運行時動態切換實現(Strategy 模式基礎)。
  • Java 實踐:List<T> vs ArrayList、DataSource vs DruidDataSource、Mapper 接口 vs MyBatis 動態代理實現。

原則二:優先使用對象組合,而非類繼承

維度類繼承 (白箱復用)對象組合 (黑箱復用)
綁定時機編譯期靜態運行期動態
封裝性破壞 (子類可見父類 protected/private)保持 (僅通過接口交互)
耦合度高 (父類變更波及所有子類)低 (接口穩定,實現可獨立演進)
靈活性低 (無法運行時切換父類實現)高 (可運行時替換組合對象)
類爆炸風險高 (多維度變化導致笛卡爾積子類)低 (維度正交,組合數線性增長)

誤區澄清:非完全否定繼承。「是一種」關係 (Liskov 替換原則成立) 用繼承;「有一個」關係 用組合。實際多為混合:抽象骨架用繼承 (AbstractTemplate),變化策略用組合 (Strategy)。

原則三:識別變化維度,應用經典模式

  • Bridge:抽象與實現分離 (如:形狀/繪圖 API、驅動程序/硬件)
  • Composite:部分-整體樹結構 (如:文件系統、UI 組件樹、菜單)
  • Decorator:動態添加職責 (如:I/O 流、HTTP 請求攔截器)
  • Observer:發布-訂閱解耦 (如:事件總線、模型-視圖同步)
  • Strategy:算法族封裝可換 (如:排序、壓縮、支付渠道、導出格式)

實戰案例:文檔多格式輸出系統

❌ 反面教材:繼承體系爆炸

abstract class AbstractExampleDocument {
    public void output(Example structure) {
        if (structure != null) this.format(structure);
    }
    protected abstract void format(Example structure);
}

// 維度 1: 格式 (Text, HTML, PDF, XML...)
// 維度 2: 結構類型 (Report, Invoice, Letter...)
// 維度 3: 壓縮 (無, GZIP, ZIP...)
// 繼承方案需創建 4×3×2 = 24 個具體子類!新增任一維度指數級增長。

✅ 正解:組合 + Strategy + Decorator

// 1. 核心抽象:文檔導出器
interface DocumentExporter {
    void export(Document doc, OutputStream out);
}

// 2. 格式策略 (Strategy)
class TextExporter implements DocumentExporter { ... }
class HtmlExporter implements DocumentExporter { ... }
class PdfExporter implements DocumentExporter { ... }

// 3. 壓縮裝飾器 (Decorator)
class CompressingExporter implements DocumentExporter {
    private DocumentExporter delegate;
    private CompressionAlgorithm algo; // GZIP, ZIP...
    public CompressingExporter(DocumentExporter delegate, CompressionAlgorithm algo) {...}
    public void export(Document doc, OutputStream out) {
        try (OutputStream compressed = algo.wrap(out)) {
            delegate.export(doc, compressed);
        }
    }
}

// 4. 客戶端組合 (運行時靈活配置)
DocumentExporter exporter = new CompressingExporter(new PdfExporter(), GZIP_ALGO);
exporter.export(doc, fileOut); // 導出壓縮 PDF
// 新增格式/壓縮算法:零修改現有代碼,僅新增實現類

總結:復用檢查清單

  1. 是否定義了穩定的接口契約?
  2. 變化點是否被封裝為可組合的組件?
  3. 是否避免了為了復用而強行繼承?
  4. 新增需求是否只需新增類,不修改舊類 (OCP)?
  5. 是否利用了經典模式詞彙溝通設計意圖?

掌握「接口+組合+模式」三位一體,復用從口號變為可執行的架構決策。

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