標籤類別指包含一個或多個「標籤欄位」來表示實例當前風格/類型的類別,並在方法中透過 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();
}
}
}
利用繼承與多態,將每種風格獨立為子類別,共同繼承抽象基類:
// 類別階層 - 簡潔、安全、可擴充
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; }
}
Circle 或 Rectangle,享受編譯期型別檢查。switch 或 if-else 依據欄位值分派行為。標籤類別是物件導向設計的反模式。Java 提供完整的繼承與多態機制,將標籤類別重構為類別階層,能從根本上解決冗長、錯誤隱患、擴充困難等問題。遇到既有標籤類別,應積極重構為階層結構。