基類 A、子類 B (擴展部分屬性/行為)。集合 A[] 混合存儲 A、B 實例。遍歷時需對 B 執行特有操作。
| 方案 | 代碼示例 | 優點 | 缺點 | 適用性 |
|---|---|---|---|---|
| instanceof + 強轉 | for (A a : list) {
if (a instanceof B) {
((B) a).specialMethod();
}
} | 直觀、無需修改類結構、性能好 | 違反開閉原則、新增子類需修改遍歷邏輯、被視為「面向對象反模式」 | 少量固定子類、臨時修復、性能極度敏感 |
| 多態重寫 | class A { void special() {} }
class B extends A { void special() { /* B 邏輯 */ } }
// 遍歷
for (A a : list) a.special(); | 純粹 OO、擴展性強、無類型檢查 | A 強制擁有無意義空方法、接口污染、違反接口隔離原則 | 子類行為差異大、需統一調用入口、領域模型清晰 |
| 類型標識方法 | class A { boolean isB() { return false; } }
class B extends A { boolean isB() { return true; } }
// 遍歷
for (A a : list) if (a.isB()) ((B)a).special(); | 避免 instanceof、語義明確、可在 A 中提供默認實現 | 本質仍是類型檢查、需強轉、新增子類需修改基類 | 不想用 instanceof 但無法引入多態的過渡方案 |
| Visitor 模式 | interface Visitor { void visit(A a); void visit(B b); }
class A { void accept(Visitor v) { v.visit(this); } }
class B extends A { void accept(Visitor v) { v.visit(this); } } | 雙分派實現類型安全操作、分離算法與對象結構 | 樣板代碼多、新增元素類需修改 Visitor 接口 | 操作邏輯複雜、多種操作、穩定類層次結構 |
| 模式匹配 (Java 17+) | for (A a : list) {
if (a instanceof B b) b.special();
} | 語法簡潔、類型安全、無強轉、編譯器穩haustiveness 檢查 | 需 JDK 17+、仍屬類型檢查範疇 | 現代 Java 項目、替代傳統 instanceof |
C 時,所有 instanceof B 檢查點均需審查修改instanceof 檢查「是什麼」,多態表達「做什麼」IF 子類行為差異大且穩定 → 多態重寫 (首選)
ELSE IF 操作邏輯多變、類層次穩定 → Visitor 模式
ELSE IF 臨時修復/少量固定子類/性能關鍵 → instanceof / 模式匹配
ELSE IF 團隊堅決反對 instanceof 但無法重構 → isB() 類型標識 (過渡)
ELSE 重新審視領域模型:是否應提取介面/組合替代繼承
B 持有 ASpecialBehavior 組件,A 委託調用B 是獨立聚合根,不應放入 A[] 混合集合sealed class A permits B, C 限制子類範圍,配合模式匹配編譯器可檢查窮盡性instanceof 使用instanceof、isB()、多態重寫、Visitor、模式匹配形成**類型分派決策光譜**。無絕對優劣,關鍵在於:**識別變化維度、評估擴展頻率、平衡純度與務實**。現代 Java (17+) 以 密封類 + 模式匹配 給出了官方認可的「受控類型檢查」方案,值得作為新項目首選基線。