繼承在編譯期確定類型與行為,運行期無法改變。濫用繼承會導致類層次膨脹、耦合加深。
通過持有介面引用,運行期動態替換實現對象,實現行為熱插拔:
interface Actor { void act(); }
class HappyActor implements Actor { public void act() { println("HappyActor"); } }
class SadActor implements Actor { public void act() { println("SadActor"); } }
class Stage {
Actor a = new HappyActor(); // 初始狀態
void change() { a = new SadActor(); } // 運行期切換行為
void go() { a.act(); }
}
Stage 不繼承 Actor,而是組合一個 Actor 引用。調用 change() 即可在運行期將行為從 Happy 切換為 Sad,無需重新編譯、無需創建新子類。
用繼承表達「行為差異」,用成員變量表達「狀態變化」。
上例中:HappyActor/SadActor繼承表達act()差異;Stage組合表達狀態變化,狀態改變同時帶來行為改變。
啟動設計時,首選組合;只有確認需要多態與向上轉型時,才引入繼承。