裝飾器模式在不修改原類、不使用繼承的情況下,動態為對象添加職責。本文以「房子裝修」為例,展示如何通過組合替代繼承,實現車庫、廚房等功能的靈活疊加,並解析 IO 流體系中的經典應用。
AbstractHouseGenericHouseMasterGarage、Kitchen// 抽象構件
interface AbstractHouse {
void doSomething();
}
// 具體構件
class GenericHouse implements AbstractHouse {
public void doSomething() {
System.out.println("具體構件:房子可居住,遮風擋雨");
}
}
// 抽象裝飾角色:持有被裝飾對象
class Master implements AbstractHouse {
protected AbstractHouse house;
public Master(AbstractHouse house) { this.house = house; }
public void doSomething() {
System.out.println("裝飾角色:持有被裝飾對象");
house.doSomething(); // 委派核心行為
}
}
// 具體裝飾:車庫
class Garage extends Master {
public Garage(AbstractHouse house) { super(house); }
public void doSomething() {
super.doSomething();
System.out.println("具體裝飾:加裝車庫,可停車");
}
}
// 具體裝飾:廚房
class Kitchen extends Master {
public Kitchen(AbstractHouse house) { super(house); }
public void doSomething() {
super.doSomething();
System.out.println("具體裝飾:加裝廚房,可做飯");
}
}
// 客戶端:動態組合
public class Demo {
public static void main(String[] args) {
AbstractHouse house = new GenericHouse();
// 疊加裝飾:先加車庫,再加廚房
house = new Kitchen(new Garage(house));
house.doSomething();
/* 輸出:
裝飾角色:持有被裝飾對象
具體構件:房子可居住,遮風擋雨
具體裝飾:加裝車庫,可停車
具體裝飾:加裝廚房,可做飯
*/
}
}
JDK IO 是裝飾器模式教科書級應用:
// 节点流(具體構件)
FileInputStream fis = new FileInputStream("a.txt");
// 疊加裝飾器
BufferedInputStream bis = new BufferedInputStream(fis); // 緩衝
DataInputStream dis = new DataInputStream(bis); // 基本類型讀取
ObjectInputStream ois = new ObjectInputStream(dis); // 對象反序列化
// 每層裝飾器增強特定能力,組合靈活,無繼承爆炸
| 維度 | 繼承 | 裝飾器 | 代理 |
|---|---|---|---|
| 關係 | is-a | has-a(組合) | has-a |
| 擴展時機 | 編譯期靜態 | 運行期動態 | 運行期動態 |
| 目的 | 特化行為 | 增強職責 | 控制訪問/隱藏細節 |
| 疊加 | 單繼承受限 | 無限疊加 | 通常單層 |
裝飾器模式是「組合優於繼承」原則的典範實踐,善用它能構建極具彈性的系統架構。