假設Stack繼承ArrayList實現,後發現性能不佳,重寫Stack改用數組+批量複製push_many()優化。但派生類MonitorableStack覆寫push()記錄高水位標記,因push_many()不再調用push(),導致監計邏輯失效。基類內部實現變更破壞派生類行為,且無法通過「小心」規避——這就是脆弱基類問題。
若Stack為接口,SimpleStack與MonitorableStack分別實現,代碼更健壯。接口強制實現類提供所有方法,無「繼承實現」耦合。復用通過組合/委派而非繼承:
interface Stack {
void push(Object o);
Object pop();
void push_many(Object[] source);
}
class SimpleStack implements Stack {
private int sp = -1;
private Object[] stack = new Object[1000];
public void push(Object o) { /* ... */ }
public Object pop() { /* ... */ }
public void push_many(Object[] src) {
System.arraycopy(src, 0, stack, sp+1, src.length);
sp += src.length;
}
}
class MonitorableStack implements Stack {
private Stack delegate = new SimpleStack(); // 組合
private int highWaterMark = 0;
public void push(Object o) {
delegate.push(o);
highWaterMark = Math.max(highWaterMark, size());
}
public void push_many(Object[] src) {
delegate.push_many(src);
highWaterMark = Math.max(highWaterMark, size());
}
// 其他方法委派給delegate...
}
雖需編寫委派樣板代碼,但消除了關鍵潛在Bug,成本極低。組合優於繼承,接口+委派實現同樣靈活的多態復用,卻避免了實現繼承的脆弱性。