當繼承階層過深時,就出現 Deep Hierarchy。
核心定義#
經驗法則:階層深度超過六層即可視為過深。
過深的階層帶來:
- 葉子類別繼承大量方法 → 行為難以預測。
- 父類別中的方法可能被多次覆寫 → 葉子層的語意不明確。
- 父類別的欄位可能被子類別中的局部變數遮蓋(shadow)→ 難以追蹤。
Deep Hierarchy 與 Speculative Hierarchy 經常同時出現:當為了未來預留中介型別時,深度自然就會增加。但兩者本質不同。
常見成因#
- 過度追求重用:以中介抽象「方便重用」為名,犧牲理解性。
- 推測性泛化:未來防備同時拉長階層。
範例#
範例 1:DatagramChannel#
java.nio.channels.DatagramChannel 的:
- 介面繼承樹深度:7
- 類別繼承樹深度:4
總共難以一眼釐清關係。

Figure 6.23: java.nio.channels 中 DatagramChannel 的繼承階層
範例 2:SynthCheckBoxUI#
javax.swing.plaf.synth.SynthCheckBoxUI 是個深而 list-like 的階層。每層只新增少量方法,部分方法在中間層級被覆寫——理解某個被繼承方法的真實語意非常費力。

Figure 6.24: SynthCheckBoxUI 類別的繼承階層
建議重構#
套用 collapse hierarchy:移除多餘或推測性的中介抽象。

Figure 6.25: 對 Deep Hierarchy 套用 collapse hierarchy 重構
範例 1 的重構#
InterruptibleChannel 是個 marker interface,只用於 instanceof 檢查。Java 1.5 引入註解後,marker interface 可以改用 @interface,藉此縮短階層深度。
範例 2 的重構#
ButtonUI 抽象類別本身沒有任何成員——它也只用來「標記」型別。可改用註解或合併。
軼事:Deep Hierarchy 引發的記憶體問題#
一個遠端裝置監控應用為每種裝置建立一個類別,並組成階層。隨著新裝置加入,階層越來越深。 葉子物件因此繼承了祖先所有的成員變數——很多其實沒在用。每個葉子物件數百 KB,數千個物件同時存在 → 記憶體耗盡 → 效能崩潰。
教訓:設計結構直接影響執行期品質。
對品質屬性的衝擊#
- 理解性:葉子類別繼承大量方法、行為難預測。
- 可變更性與可擴充性:改父型別波及所有子孫;新增子型別也需要思考所有層級。
- 可測試性:被覆寫多次的方法測試成本高。
- 可靠性:方法覆寫與欄位遮蓋容易引發執行期錯誤。
別名#
- Distorted hierarchy:階層異常窄而深。
實務考量:促進重用#
Deep Hierarchy 的確能促進重用——成熟的框架/函式庫常有深階層。設計者應在重用 vs.(理解性、可變更性、可擴充性、可靠性、效能)之間有意識地權衡。