咖啡店飲料種類繁多(濃縮、拿鐵、摩卡…),調料更多(牛奶、糖漿、巧克力碎…)。若用繼承為每種組合建類,類數量爆炸(MochaWithMilkAndSugar 等)。裝飾者模式以組合替代繼承,動態為對象添加職責。
Beverage)Espresso, DarkRoast)Milk, Soy, Whip),增強行為後調用被裝飾對象description(); }
double cost() const override { return beverage->cost(); }
};
// ConcreteDecorators
class Milk : public CondimentDecorator {
public:
Milk(Beverage* b) : CondimentDecorator(b) {}
string description() const override { return beverage->description() + ", Milk"; }
double cost() const override { return beverage->cost() + 0.10; }
};
class Whip : public CondimentDecorator {
public:
Whip(Beverage* b) : CondimentDecorator(b) {}
string description() const override { return beverage->description() + ", Whip"; }
double cost() const override { return beverage->cost() + 0.15; }
};
// 使用
int main() {
Beverage* drink = new Espresso();
drink = new Milk(drink);
drink = new Whip(drink);
cout << drink->description() << " $" << drink->cost() << endl;
// Espresso, Milk, Whip $2.24
delete drink; // 需遞歸刪除或用 smart pointer
}
new Whip(new Milk(new Espresso())))。| 優點 | 缺點 |
|---|---|
| 比繼承靈活,避免類爆炸 | 產生大量小對象,調試困難 |
| 可任意組合行為 | 過度使用導致代碼難以理解 |
| 符合開閉原則 | 裝飾層過深可能影響性能 |