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

C++ 設計模式:裝飾者模式 深度解析與咖啡店實例

     編輯:關於C++

模式動機

咖啡店飲料種類繁多(濃縮、拿鐵、摩卡…),調料更多(牛奶、糖漿、巧克力碎…)。若用繼承為每種組合建類,類數量爆炸(MochaWithMilkAndSugar 等)。裝飾者模式以組合替代繼承,動態為對象添加職責。

UML 角色

  • Component:抽象接口(Beverage)
  • ConcreteComponent:具體對象(Espresso, DarkRoast)
  • Decorator:抽象裝飾者,持有 Component 指針,轉發請求
  • ConcreteDecorator:具體調料(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
}

關鍵設計要點

  1. 接口一致性:Decorator 繼承 Component,保證類型兼容。
  2. 透明性:客戶端無需知道是否被裝飾,統一用 Component 接口。
  3. 動態組合:運行時決定裝飾層數與順序(new Whip(new Milk(new Espresso())))。
  4. 單一職責:每個裝飾類只關注一種調料邏輯。

適用場景

  • 需要動態、可撤銷地為對象添加職責
  • 避免因功能組合導致的子類爆炸
  • 無法使用繼承(類被 final、或為第三方庫)

優缺點

優點缺點
比繼承靈活,避免類爆炸產生大量小對象,調試困難
可任意組合行為過度使用導致代碼難以理解
符合開閉原則裝飾層過深可能影響性能
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved