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

Effective Java 實戰:以類別階層取代標籤類別

     編輯:Java 綜合教學

Effective Java 實戰:以類別階層取代標籤類別

什麼是標籤類別?

標籤類別指包含一個或多個「標籤欄位」來表示實例當前風格/類型的類別,並在方法中透過 switch 或 if-else 根據標籤分派行為。例如同時表示圓形與矩形的 Figure 類別:

// 標籤類別 - 缺點多多
class Figure {
    enum Shape { RECTANGLE, CIRCLE }
    final Shape shape;           // 標籤欄位
    double length, width;        // 僅矩形使用
    double radius;               // 僅圓形使用

    Figure(double radius) { shape = Shape.CIRCLE; this.radius = radius; }
    Figure(double length, double width) { shape = Shape.RECTANGLE; this.length = length; this.width = width; }

    double area() {
        switch (shape) {
            case RECTANGLE: return length * width;
            case CIRCLE: return Math.PI * radius * radius;
            default: throw new AssertionError();
        }
    }
}

標籤類別的五大缺點

  1. 樣板代碼氾濫: 枚舉、標籤欄位、條件分支混雜,可讀性差。
  2. 記憶體浪費: 每個實例都攜帶其他風格無關的欄位 (如圓形實例仍佔用 length/width)。
  3. 欄位無法設為 final: 因構造器需初始化無關欄位,或需額外邏輯設置標籤,易導致運行時錯誤。
  4. 擴充困難: 新增風格需修改源碼,並在每個 switch 中添加 case,否則運行時失敗。
  5. 型態資訊缺失: 實例型態無法反映其風格,無法利用編譯期型別檢查。

重構為類別階層

利用繼承與多態,將每種風格獨立為子類別,共同繼承抽象基類:

// 類別階層 - 簡潔、安全、可擴充
abstract class Figure {
    abstract double area();
}

class Circle extends Figure {
    final double radius;
    Circle(double radius) { this.radius = radius; }
    @Override double area() { return Math.PI * radius * radius; }
}

class Rectangle extends Figure {
    final double length, width;
    Rectangle(double length, double width) { this.length = length; this.width = width; }
    @Override double area() { return length * width; }
}

類別階層的優勢

  • 代碼簡潔: 無樣板代碼,各類別職責單一。
  • 記憶體高效: 實例僅包含自身相關欄位。
  • 欄位可為 final: 編譯器強制構造器初始化所有 final 欄位。
  • 編譯期安全: 抽象方法強制子類實作,避免漏寫 case 導致的運行時錯誤。
  • 開放擴充: 任何人可獨立新增子類別,無需修改基類源碼 (開放封閉原則)。
  • 型別精確: 變數可宣告為 Circle 或 Rectangle,享受編譯期型別檢查。
  • 反映領域層次: 自然表達「是一種」關係,增強語義表達力。

何時考慮重構?

  • 發現類別中有 switch 或 if-else 依據欄位值分派行為。
  • 類別包含僅在特定情況下使用的欄位。
  • 需頻繁新增「風格/類型」且不想修改既有核心代碼。

總結

標籤類別是物件導向設計的反模式。Java 提供完整的繼承與多態機制,將標籤類別重構為類別階層,能從根本上解決冗長、錯誤隱患、擴充困難等問題。遇到既有標籤類別,應積極重構為階層結構。

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