裝飾器模式:動態地給一個對象添加額外職責。就增加功能而言,裝飾器模式比生成子類更為靈活。別名:包裝器模式。
| 角色 | 說明 | IO 流對應 | 示例類 |
|---|---|---|---|
| Component (抽象構件) | 定義對象接口,規範核心行為 | InputStream / OutputStream / Reader / Writer | Component 接口 |
| ConcreteComponent (具體構件) | 被裝飾的基礎對象 | FileInputStream / FileOutputStream | ConcreteComponent |
| Decorator (抽象裝飾器) | 持有 Component 引用,實現 Component 接口,委派調用 | FilterInputStream / FilterOutputStream | Decorator 抽象類 |
| ConcreteDecorator (具體裝飾器) | 具體增強邏輯 (緩衝、轉換、壓縮、加密...) | BufferedInputStream / DataInputStream / GZIPInputStream / CipherInputStream | ConcreteDecoratorA/B |
public interface Component {
void doSomething();
}
public class ConcreteComponent implements Component {
@Override
public void doSomething() {
System.out.println("核心功能 A");
}
}
public abstract class Decorator implements Component {
protected final Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void doSomething() {
component.doSomething(); // 委派
}
}
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void doSomething() {
super.doSomething(); // 執行核心/上層裝飾邏輯
doAnotherThing(); // 新增功能 B
}
private void doAnotherThing() {
System.out.println("增強功能 B");
}
}
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void doSomething() {
super.doSomething();
doAnotherThing(); // 新增功能 C
}
private void doAnotherThing() {
System.out.println("增強功能 C");
}
}
public class Client {
public static void main(String[] args) {
// 從內向外層層包裝:核心 -> 功能 C -> 功能 B
Component component = new ConcreteDecoratorA(
new ConcreteDecoratorB(
new ConcreteComponent()
));
component.doSomething();
// 輸出順序:
// 核心功能 A
// 增強功能 C
// 增強功能 B
}
}
| 維度 | 繼承 | 裝飾器 |
|---|---|---|
| 綁定時間 | 編譯期靜態 | 運行期動態 |
| 功能組合 | 單一繼承鏈,排列組合爆炸 | 任意組合、層疊、移除 |
| 擴展性 | 違反開閉原則 (修改父類/子類) | 符合開閉原則 (新增裝飾器類) |
| 對象身份 | 子類即父類 | 裝飾器非被裝飾對象 (instanceof 需謹慎) |
| 代碼複雜度 | 類數量少,但層次深 | 類數量多 (每功能一類),結構扁平 |
// 輸入流鏈:文件 -> 緩衝 -> 數據類型讀取 -> 對象反序列化
InputStream is = new FileInputStream("data.bin");
is = new BufferedInputStream(is); // 增強:緩衝讀取,減少系統調用
is = new DataInputStream(is); // 增強:按基本類型讀取 (readInt/readUTF)
is = new ObjectInputStream(is); // 增強:對象反序列化
Object obj = is.readObject();
// 輸出流鏈:文件 -> 緩衝 -> GZIP 壓縮 -> 加密
OutputStream os = new FileOutputStream("data.gz.enc");
os = new BufferedOutputStream(os); // 緩衝
os = new GZIPOutputStream(os); // 壓縮
os = new CipherOutputStream(os, cipher); // 加密
os.write(data);
每一層裝飾器只關注單一職責,客戶端按需組裝,極致體現「單一職責原則」與「開閉原則」。
@Decorator / BeanPostProcessor / AOP 代理本質均為裝飾器模式變體。Function<T,T> 組合,無需額外類定義。
Function<String, String> trim = String::trim;
Function<String, String> upper = String::toUpperCase;
Function<String, String> decorate = trim.andThen(upper); // 組合
String result = decorate.apply(" hello "); // "HELLO"
裝飾器模式以「組合代替繼承」為核心,提供了運行期動態擴展對象功能的強大能力。Java IO 流體系是其最經典實踐,Spring AOP、Servlet Filter、Netty ChannelHandler 等框架級組件均深受其影響。掌握「抽象構件 → 具體構件 → 抽象裝飾器 → 具體裝飾器」四角色結構,理解委派調用與層疊增強機制,即可在業務代碼中靈活應用,構建高內聚、低耦合、易擴展的系統架構。