C++ 装饰器模式详解
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象动态添加新的功能,同时不改变其结构。这种模式创建了一个装饰类,用来包装原有的类,提供了比继承更有弹性的替代方案。
核心概念
设计原则
装饰器模式遵循开闭原则(Open/Closed Principle):
-
对扩展开放:可以通过装饰器添加新功能
-
对修改关闭:不需要修改现有代码
主要优点
-
灵活扩展:比继承更灵活,可以动态添加或删除功能
-
避免类爆炸:不需要为每种功能组合创建子类
-
保持单一职责:每个装饰类只关注特定功能
-
运行时配置:可以在运行时选择不同的装饰组合
模式结构
主要组件
-
Component(组件接口)
-
定义对象的接口
-
可以是抽象类或接口
-
-
ConcreteComponent(具体组件)
-
实现组件接口的基本功能
-
将被装饰的对象
-
-
Decorator(装饰器基类)
-
继承/实现组件接口
-
持有组件对象的引用
-
-
ConcreteDecorator(具体装饰器)
-
向组件添加具体的新功能
-
可以在调用前后添加行为
#include <iostream> #include <memory> #include <string>// ==================== 组件接口 ==================== class Beverage { public:virtual std::string getDescription() const = 0;virtual double cost() const = 0;virtual ~Beverage() = default; };// ==================== 具体组件 ==================== class Espresso : public Beverage { public:std::string getDescription() const override {return "浓缩咖啡";}double cost() const override {return 1.99;} };class HouseBlend : public Beverage { public:std::string getDescription() const override {return "家常混合咖啡";}double cost() const override {return 0.89;} };// ==================== 装饰器基类 ==================== class CondimentDecorator : public Beverage { protected:std::unique_ptr<Beverage> beverage_;public:explicit CondimentDecorator(std::unique_ptr<Beverage> beverage): beverage_(std::move(beverage)) {}std::string getDescription() const override = 0; };// ==================== 具体装饰器 ==================== class Milk : public CondimentDecorator { public:explicit Milk(std::unique_ptr<Beverage> beverage): CondimentDecorator(std::move(beverage)) {}std::string getDescription() const override {return beverage_->getDescription() + ",加牛奶";}double cost() const override {return beverage_->cost() + 0.20;} };class Mocha : public CondimentDecorator { public:explicit Mocha(std::unique_ptr<Beverage> beverage): CondimentDecorator(std::move(beverage)) {}std::string getDescription() const override {return beverage_->getDescription() + ",加摩卡";}double cost() const override {return beverage_->cost() + 0.30;} };class Whip : public CondimentDecorator { public:explicit Whip(std::unique_ptr<Beverage> beverage): CondimentDecorator(std::move(beverage)) {}std::string getDescription() const override {return beverage_->getDescription() + ",加奶泡";}double cost() const override {return beverage_->cost() + 0.15;} };// ==================== 客户端代码 ==================== int main() {std::cout << "=== 咖啡订单系统 ===" << std::endl;// 1. 单纯浓缩咖啡auto espresso = std::make_unique<Espresso>();std::cout << "订单1: " << espresso->getDescription() << " 价格: ¥" << espresso->cost() << std::endl;// 2. 家常混合咖啡 + 双倍摩卡 + 奶泡auto houseBlend = std::make_unique<HouseBlend>();houseBlend = std::make_unique<Mocha>(std::move(houseBlend));houseBlend = std::make_unique<Mocha>(std::move(houseBlend));houseBlend = std::make_unique<Whip>(std::move(houseBlend));std::cout << "订单2: " << houseBlend->getDescription() << " 价格: ¥" << houseBlend->cost() << std::endl;// 3. 浓缩咖啡 + 牛奶 + 奶泡auto espressoWithCondiments = std::make_unique<Espresso>();espressoWithCondiments = std::make_unique<Milk>(std::move(espressoWithCondiments));espressoWithCondiments = std::make_unique<Whip>(std::move(espressoWithCondiments));std::cout << "订单3: " << espressoWithCondiments->getDescription() << " 价格: ¥" << espressoWithCondiments->cost() << std::endl;return 0; }
模式变体
1. 带状态的装饰器
class SizeDecorator : public CondimentDecorator {enum Size { SMALL, MEDIUM, LARGE };Size size_;public:SizeDecorator(std::unique_ptr<Beverage> beverage, Size size): CondimentDecorator(std::move(beverage)), size_(size) {}std::string getDescription() const override {std::string sizeStr;switch(size_) {case SMALL: sizeStr = "小杯"; break;case MEDIUM: sizeStr = "中杯"; break;case LARGE: sizeStr = "大杯"; break;}return beverage_->getDescription() + "," + sizeStr;}double cost() const override {double baseCost = beverage_->cost();switch(size_) {case SMALL: return baseCost * 0.8;case MEDIUM: return baseCost;case LARGE: return baseCost * 1.2;}return baseCost;} };
2. 接口增强装饰器
class DiscountDecorator : public Beverage {std::unique_ptr<Beverage> beverage_;double discountRate_;public:DiscountDecorator(std::unique_ptr<Beverage> beverage, double rate): beverage_(std::move(beverage)), discountRate_(rate) {}std::string getDescription() const override {return beverage_->getDescription() + "(折扣" + std::to_string(discountRate_*100) + "%)";}double cost() const override {return beverage_->cost() * (1 - discountRate_);}// 新增方法double getOriginalPrice() const {return beverage_->cost();} };
实际应用场景
-
GUI组件装饰:为UI控件添加边框、滚动条等功能
-
I/O流处理:Java/C#中的BufferedStream等
-
中间件管道:Web框架的请求处理管道
-
游戏角色装备:动态添加武器、防具等效果
-
日志系统:添加时间戳、日志级别等装饰
-