🎯 什麼情境該想到我

當你「想在不改動原類別、也不用一堆子類別的前提下,動態地幫某個物件疊上額外功能,而且這些功能要能任意組合(例如 I/O 串流疊上緩衝+壓縮+加密、給 UI 元件加邊框+捲軸、給服務加日誌+快取)」的時候。

⚙️ 怎麼用(步驟 / 公式)

意圖:動態地給物件附加額外的職責。就擴充功能而言,裝飾者是「用子類繼承來擴充」的一種有彈性的替代方案。

主要參與者 / 結構:

  • Component(元件):被裝飾者與裝飾者共同的介面。
  • ConcreteComponent(具體元件):被包裝的核心物件。
  • Decorator(裝飾者):實作 Component 介面,並持有一個 Component 的參照(被它包住的對象)。
  • ConcreteDecorator(具體裝飾者):在轉呼叫給內層物件的前後,加上自己的行為。

做法要點:

  1. 讓裝飾者與被裝飾者實作同一個 Component 介面(對客戶端而言兩者可互換)。
  2. 裝飾者持有一個 Component 參照,方法內先/後加行為,中間委派給內層。
  3. 因為介面相同,裝飾者可以層層包裹,執行期自由堆疊組合。

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 會產生很多外觀相似的小物件,堆疊多層後要看懂「這個物件到底被包了幾層、順序如何」很吃力,除錯困難。
  • 裝飾者與內層物件並非同一個物件,若程式碼依賴物件識別(identity)或型別判斷會出問題。
  • 這是「組合優於繼承」的具體實踐;但若功能組合固定、數量少,直接寫死可能更簡單。

🔗 相關工具