C++ 设计模式 《小明的奶茶加料风波》

发布于:2025-06-11 ⋅ 阅读:(39) ⋅ 点赞:(0)

👨‍🎓 模式名称:装饰器模式(Decorator Pattern)

👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料:
有的同学要加波霸 🟤,有的要加椰果 🥥,还有的要加奶盖 🥛。
但每个“加料”组合都要写一个新类?小明一开始不以为意,直到……

❌ 没使用装饰器模式的惨状:

#include <iostream>
#include <string>

class MilkTea {
public:
    virtual std::string getDescription() = 0;
    virtual double cost() = 0;
    virtual ~MilkTea() {}
};

class OriginalMilkTea : public MilkTea {
public:
    std::string getDescription() override {
        return "原味奶茶";
    }
    double cost() override {
        return 8.0;
    }
};

class MilkTeaWithBoba : public MilkTea {
public:
    std::string getDescription() override {
        return "原味奶茶 + 波霸";
    }
    double cost() override {
        return 10.0;
    }
};

class MilkTeaWithBobaAndCheese : public MilkTea {
public:
    std::string getDescription() override {
        return "原味奶茶 + 波霸 + 奶盖";
    }
    double cost() override {
        return 13.0;
    }
};

int main() {
    MilkTea* tea1 = new OriginalMilkTea();
    MilkTea* tea2 = new MilkTeaWithBoba();
    MilkTea* tea3 = new MilkTeaWithBobaAndCheese();

    std::cout << tea3->getDescription() << " 价格:¥" << tea3->cost() << std::endl;

    delete tea1;
    delete tea2;
    delete tea3;

    return 0;
}

在这里插入图片描述

💥 小明懵了:

加个椰果再写个类?
波霸 + 奶盖 + 椰果再写?
🍵 加料 2^N 种组合,类数直接爆炸!

✅ 使用装饰器模式后:灵活加料,优雅解耦!

#include <iostream>
#include <string>
#include <memory>

// 奶茶基类
class MilkTea {
public:
    virtual std::string getDescription() = 0;
    virtual double cost() = 0;
    virtual ~MilkTea() {}
};

// 原味奶茶
class OriginalMilkTea : public MilkTea {
public:
    std::string getDescription() override {
        return "原味奶茶";
    }
    double cost() override {
        return 8.0;
    }
};

// 装饰器基类
class ToppingDecorator : public MilkTea {
protected:
    std::shared_ptr<MilkTea> tea;
public:
    ToppingDecorator(std::shared_ptr<MilkTea> t) : tea(t) {}
};

// 加波霸
class Boba : public ToppingDecorator {
public:
    Boba(std::shared_ptr<MilkTea> t) : ToppingDecorator(t) {}
    std::string getDescription() override {
        return tea->getDescription() + " + 波霸🟤";
    }
    double cost() override {
        return tea->cost() + 2.0;
    }
};

// 加奶盖
class Cheese : public ToppingDecorator {
public:
    Cheese(std::shared_ptr<MilkTea> t) : ToppingDecorator(t) {}
    std::string getDescription() override {
        return tea->getDescription() + " + 奶盖🥛";
    }
    double cost() override {
        return tea->cost() + 3.0;
    }
};

// 加椰果
class Coconut : public ToppingDecorator {
public:
    Coconut(std::shared_ptr<MilkTea> t) : ToppingDecorator(t) {}
    std::string getDescription() override {
        return tea->getDescription() + " + 椰果🥥";
    }
    double cost() override {
        return tea->cost() + 1.5;
    }
};

int main() {
    // 原味奶茶 + 波霸 + 奶盖 + 椰果!
    std::shared_ptr<MilkTea> order = std::make_shared<OriginalMilkTea>();
    order = std::make_shared<Boba>(order);
    order = std::make_shared<Cheese>(order);
    order = std::make_shared<Coconut>(order);

    std::cout << "🎉 " << order->getDescription() << " 价格:¥" << order->cost() << std::endl;
    return 0;
}

在这里插入图片描述

🧠 总结:装饰器模式的价值

问题 没使用 使用装饰器
类数量 爆炸(组合越多类越多) 只需一个装饰器类一类加料
灵活性 不能动态组合 可以任意组合加料
可维护性 每改一组合要改多个类 可拓展性强,易维护

✅ 适用场景

  • 不同功能组合需要动态叠加(如小明的加料奶茶🍵、网页组件、技能系统等)

  • 不想通过继承创建过多子类

  • 需要在运行时添加功能而非编译期


网站公告

今日签到

点亮在社区的每一天
去签到