首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 設計模式深度解析:裝飾模式(Decorator Pattern)原理與實戰

     編輯:Java 程式設計入門

裝飾模式(Decorator Pattern),又稱包裝模式,是結構型設計模式中的經典之作。它在不改變原類別、不使用繼承的前提下,動態地為物件擴展職責,完美詮釋了「開放封閉原則」與「合成復用原則」。本文將從定義、核心角色、與繼承的差異、程式碼實戰、到 Java IO 體系中的實際應用,全方位剖析此模式。

一、核心定義與動機

  • 定義:以對客戶端透明的方式,動態地給一個物件附加額外職責。
  • 關鍵詞:動態、透明、不創建子類別、組合大於繼承。
  • 解決痛點:繼承是靜態編譯期決定,若需排列組合功能會導致類別爆炸;裝飾模式將功能拆解為獨立裝飾類,執行期靈活組合。

二、四大核心角色(UML 靜態結構)

角色說明Java IO 對應範例
Component(抽象構件)定義物件介面,規範核心行為InputStream、Reader
ConcreteComponent(具體構件)被裝飾的核心物件FileInputStream、FileReader
Decorator(抽象裝飾者)持有 Component 參考,實作相同介面,委派給被裝飾者FilterInputStream、BufferedReader
ConcreteDecorator(具體裝飾者)在委派前後增加具體行為BufferedInputStream、DataInputStream、GZIPInputStream

三、裝飾模式 vs 類別繼承

維度繼承裝飾模式
綁定時機編譯期(靜態)執行期(動態)
功能組合單一繼承鏈,排列組合需建大量子類任意組合裝飾類,零類別爆炸
擴展對象類別功能物件實例功能
透明性子類型即父類型裝飾者與被裝飾者實作相同介面,客戶端無感

四、程式碼實戰:可疊加的功能增強器

// 1. 抽象構件
public interface Component {
    void doSomething();
}

// 2. 具體構件
public class ConcreteComponent implements Component {
    public void doSomething() { System.out.println("功能A"); }
}

// 3. 抽象裝飾者(持有 Component 參考)
public abstract class Decorator implements Component {
    protected Component component;
    public Decorator(Component c) { this.component = c; }
    public void doSomething() { component.doSomething(); } // 預設委派
}

// 4. 具體裝飾者 1:增加功能 B
public class ConcreteDecorator1 extends Decorator {
    public ConcreteDecorator1(Component c) { super(c); }
    public void doSomething() {
        super.doSomething();          // 執行核心/前一層功能
        doAnotherThing();             // 新增功能
    }
    private void doAnotherThing() { System.out.println("功能B"); }
}

// 5. 具體裝飾者 2:增加功能 C
public class ConcreteDecorator2 extends Decorator {
    public ConcreteDecorator2(Component c) { super(c); }
    public void doSomething() {
        super.doSomething();
        doAnotherThing();
    }
    private void doAnotherThing() { System.out.println("功能C"); }
}

// 6. 客戶端:像搭積木一樣組合
public class Client {
    public static void main(String[] args) {
        Component c = new ConcreteDecorator1(
                        new ConcreteDecorator2(
                            new ConcreteComponent()));
        c.doSomething(); 
        // 輸出:功能A → 功能C → 功能B(由內而外疊加)
    }
}

五、裝飾模式四大特徵(記憶口訣:同介、含引、轉發、增強)

  1. 同介面:裝飾者與被裝飾者實作相同介面。
  2. 含引用:裝飾者內部持有 Component 參考。
  3. 轉發請求:所有客戶端呼叫先到達裝飾者,再委派給被裝飾者。
  4. 增強功能:在轉發前/後插入額外邏輯,不修改原物件結構。

六、Java 標準庫中的教科書級應用:IO 流體系

// 核心節點(ConcreteComponent)
FileInputStream fis = new FileInputStream("data.txt");

// 層層裝飾:緩衝 → 資料型別轉換 → 物件序列化
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
ObjectInputStream ois = new ObjectInputStream(dis);

// 客戶端只看到 InputStream 介面,完全不知內部已疊加三層功能
int i = dis.readInt();
Object obj = ois.readObject();

每一層 XXXInputStream 都是具體裝飾者,新增緩衝、基本型別讀取、物件反序列化等能力,卻統一實作 InputStream 介面,完美示範裝飾模式精髓。

七、適用場景與注意事項

  • ✅ 需在執行期動態、透明地為單一物件新增職責。
  • ✅ 需支援功能的任意排列組合,避免子類別爆炸。
  • ✅ 無法使用繼承(final 類別、封裝庫)時的替代方案。
  • ⚠️ 過度使用會產生大量細小類別,增加除錯與閱讀難度。
  • ⚠️ 裝飾者與被裝飾者型別不同(雖實作同介面),instanceof 判斷需謹慎。

八、總結

裝飾模式以「組合取代繼承」,在執行期為物件動態貼上功能標籤,是 Java IO、Servlet Filter、Spring AOP 代理鏈等眾多框架的核心架構基石。掌握其「同介面、持引用、轉發、增強」四步曲,即可輕鬆駕馭靈活的功能擴展藝術。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved