
想幫一杯美式咖啡加牛奶再加糖,你會寫一個 AmericanoWithMilkAndSugar class 嗎?那如果還要加鮮奶油呢?再來一個 AmericanoWithMilkAndSugarAndCream?
這就是繼承的噩夢——而 Decorator 是解藥。
先講結論
Decorator Pattern 的核心思想:用包裝取代繼承。你有一個基礎物件,想加功能?包一層。再加功能?再包一層。每一層都不改原本的 code,但組合起來就能做到任何你想要的效果。
classDiagram class Component { <<interface>> +cost()* number +description()* String } class BasicCoffee { +cost() number +description() String } class Decorator { -coffee : Component +cost() number +description() String } class MilkDecorator { +cost() number } class SugarDecorator { +cost() number } Component <|.. BasicCoffee Component <|.. Decorator Decorator <|-- MilkDecorator Decorator <|-- SugarDecorator Decorator --> Component
經典範例:咖啡點餐系統
class BasicCoffee {
cost() { return 50; }
description() { return '美式咖啡'; }
}
class Decorator {
constructor(coffee) { this.coffee = coffee; }
cost() { return this.coffee.cost(); }
description() { return this.coffee.description(); }
}
class MilkDecorator extends Decorator {
cost() { return super.cost() + 20; }
description() { return `${super.description()} + 牛奶`; }
}
class SugarDecorator extends Decorator {
cost() { return super.cost() + 10; }
description() { return `${super.description()} + 糖`; }
}
let coffee = new BasicCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
console.log(coffee.description()); // 美式咖啡 + 牛奶 + 糖
console.log(coffee.cost()); // 80每個 Decorator 都只知道「我包住的那杯東西」和「我要加什麼」。想加鮮奶油?寫一個 CreamDecorator,不用動任何既有程式碼。
真實世界在哪用?
你可能已經用過了:
- Express/Koa middleware:每個 middleware 就是一個 Decorator,包在 request 處理流程外面
- TypeScript/Python 的
@decorator語法:直接語言層級支援 - Java I/O Stream:
new BufferedReader(new InputStreamReader(new FileInputStream("file")))——標準的三層 Decorator
Decorator vs 繼承
用繼承的話,M 種配料的組合就是 2^M 個 class。用 Decorator 的話,M 種配料就是 M 個 Decorator class,隨意組合。
不過 Decorator 也不是萬能的——疊太多層的時候 debug 會很痛苦,因為你要一層一層剝開才知道哪層出問題。三層以內通常沒問題,超過五層就該重新思考架構了。
Decorator Pattern 就像幫手機貼保護貼、裝殼、掛吊飾——手機本身沒變,但功能和外觀都不一樣了。只是你疊了太多層以後,手機就變成一塊磚頭了。
延伸閱讀
- Proxy 模式 — Proxy 控制存取,Decorator 擴充行為
- Adapter 模式 — 同屬結構型模式
- Strategy 模式 — 透過策略替換改變行為
- Composite 模式 — 樹狀結構統一處理