第九章:装饰器模式 - 动态增强的艺术大师
第九章:装饰器模式 - 动态增强的艺术大师
故事延续:功能装饰的灵活之道
在Composite展示完他的组合艺术后,Decorator珠光宝气、华服层叠地走出,他摇着一把镶满宝石的扇子,优雅登场。这位贵公子的声音温和而富有磁性,每个动作都透露出精致与优雅。
"Composite兄的层次结构确实统一,"Decorator笑道,“但若想给对象动态添加功能,就需要我的装饰模式了。我的武学核心在于——动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。”
装饰器模式的武学精要
核心心法
Decorator展开他那镶满宝石的扇子,空中浮现出层层叠加的装饰效果:“我的十六字真言是——动态装饰,透明扩展。通过创建装饰器类来包装原始对象,我可以在运行时透明地添加无限多的功能,而不会影响其他对象。”
C++ 代码实战
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>// 组件接口:咖啡
class Coffee {
public:virtual ~Coffee() = default;virtual std::string getDescription() const = 0;virtual double getCost() const = 0;virtual int getCalories() const = 0;virtual void prepare() const = 0;// 虚函数用于克隆virtual std::unique_ptr<Coffee> clone() const = 0;
};// 具体组件:基础咖啡
class BasicCoffee : public Coffee {
private:std::string description_;double baseCost_;int baseCalories_;public:BasicCoffee(const std::string& description, double cost, int calories): description_(description), baseCost_(cost), baseCalories_(calories) {}std::string getDescription() const override {return description_;}double getCost() const override {return baseCost_;}int getCalories() const override {return baseCalories_;}void prepare() const override {std::cout << "☕ 准备 " << description_ << std::endl;}std::unique_ptr<Coffee> clone() const override {return std::make_unique<BasicCoffee>(*this);}
};// 装饰器基类
class CoffeeDecorator : public Coffee {
protected:std::unique_ptr<Coffee> decoratedCoffee_;public:CoffeeDecorator(std::unique_ptr<Coffee> coffee) : decoratedCoffee_(std::move(coffee)) {}std::string getDescription() const override {return decoratedCoffee_->getDescription();}double getCost() const override {return decoratedCoffee_->getCost();}int getCalories() const override {return decoratedCoffee_->getCalories();}void prepare() const override {decoratedCoffee_->prepare();}std::unique_ptr<Coffee> clone() const override {auto clonedBase = decoratedCoffee_->clone();return std::make_unique<CoffeeDecorator>(std::move(clonedBase));}
};// 具体装饰器:牛奶装饰器
class MilkDecorator : public CoffeeDecorator {
private:double milkCost_;int milkCalories_;public:MilkDecorator(std::unique_ptr<Coffee> coffee, double cost = 1.5, int calories = 50): CoffeeDecorator(std::move(coffee)), milkCost_(cost), milkCalories_(calories) {}std::string getDescription() const override {return decoratedCoffee_->getDescription() + " + 牛奶";}double getCost() const override {return decoratedCoffee_->getCost() + milkCost_;}int getCalories() const override {return decoratedCoffee_->getCalories() + milkCalories_;}void prepare() const override {decoratedCoffee_->prepare();std::cout << "🥛 加入新鲜牛奶" << std::endl;}std::unique_ptr<Coffee> clone() const override {auto clonedBase = decoratedCoffee_->clone();return std::make_unique<MilkDecorator>(std::move(clonedBase), milkCost_, milkCalories_);}// 牛奶特有方法void setMilkType(const std::string& type) {std::cout << "🥛 设置牛奶类型: " << type << std::endl;}
};// 具体装饰器:糖装饰器
class SugarDecorator : public CoffeeDecorator {
private:double sugarCost_;int sugarCalories_;int sugarSpoons_;public:SugarDecorator(std::unique_ptr<Coffee> coffee, int spoons = 1, double cost = 0.5, int calories = 20): CoffeeDecorator(std::move(coffee)), sugarCost_(cost), sugarCalories_(calories * spoons), sugarSpoons_(spoons) {}std::string getDescription() const override {return decoratedCoffee_->getDescription() + " + " + std::to_string(sugarSpoons_) + "勺糖";}double getCost() const override {return decoratedCoffee_->getCost() + sugarCost_;}int getCalories() const override {return decoratedCoffee_->getCalories() + sugarCalories_;}void prepare() const override {decoratedCoffee_->prepare();std::cout << "🍬 加入 " << sugarSpoons_ << " 勺糖" << std::endl;}std::unique_ptr<Coffee> clone() const override {auto clonedBase = decoratedCoffee_->clone();return std::make_unique<SugarDecorator>(std::move(clonedBase), sugarSpoons_, sugarCost_, sugarCalories_ / sugarSpoons_);}// 糖特有方法void adjustSweetness(int spoons) {sugarSpoons_ = spoons;sugarCalories_ = 20 * spoons;std::cout << "🎛️ 调整甜度: " << spoons << " 勺糖" << std::endl;}
};// 具体装饰器:奶油装饰器
class CreamDecorator : public CoffeeDecorator {
private:double creamCost_;int creamCalories_;public:CreamDecorator(std::unique_ptr<Coffee> coffee, double cost = 2.0, int calories = 100): CoffeeDecorator(std::move(coffee)), creamCost_(cost), creamCalories_(calories) {}std::string getDescription() const override {return decoratedCoffee_->getDescription() + " + 奶油";}double getCost() const override {return decoratedCoffee_->getCost() + creamCost_;}int getCalories() const override {return decoratedCoffee_->getCalories() + creamCalories_;}void prepare() const override {decoratedCoffee_->prepare();std::cout << "🍦 加入 whipped cream" << std::endl;}std::unique_ptr<Coffee> clone() const override {auto clonedBase = decoratedCoffee_->clone();return std::make_unique<CreamDecorator>(std::move(clonedBase), creamCost_, creamCalories_);}// 奶油特有方法void addChocolateShavings() {std::cout = "🍫 加入巧克力碎屑" << std::endl;}
};// 具体装饰器:香料装饰器
class SpiceDecorator : public CoffeeDecorator {
private:std::string spiceType_;double spiceCost_;int spiceCalories_;public:SpiceDecorator(std::unique_ptr<Coffee> coffee, const std::string& spice, double cost = 1.0, int calories = 5): CoffeeDecorator(std::move(coffee)), spiceType_(spice), spiceCost_(cost), spiceCalories_(calories) {}std::string getDescription() const override {return decoratedCoffee_->getDescription() + " + " + spiceType_;}double getCost() const override {return decoratedCoffee_->getCost() + spiceCost_;}int getCalories() const override {return decoratedCoffee_->getCalories() + spiceCalories_;}void prepare() const override {decoratedCoffee_->prepare();std::cout << "🌶️ 撒上 " << spiceType_ << std::endl;}std::unique_ptr<Coffee> clone() const override {auto clonedBase = decoratedCoffee_->clone();return std::make_unique<SpiceDecorator>(std::move(clonedBase), spiceType_, spiceCost_, spiceCalories_);}// 香料特有方法void changeSpice(const std::string& newSpice) {spiceType_ = newSpice;std::cout << "🔄 更换香料为: " << newSpice << std::endl;}
};// 具体装饰器:冰装饰器
class IceDecorator : public CoffeeDecorator {
private:int iceLevel_; // 1-3级public:IceDecorator(std::unique_ptr<Coffee> coffee, int level = 2): CoffeeDecorator(std::move(coffee)), iceLevel_(level) {}std::string getDescription() const override {std::string levelDesc;switch(iceLevel_) {case 1: levelDesc = "少冰"; break;case 2: levelDesc = "正常冰"; break;case 3: levelDesc = "多冰"; break;default: levelDesc = "正常冰";}return decoratedCoffee_->getDescription() + " + " + levelDesc;}double getCost() const override {return decoratedCoffee_->getCost(); // 冰块通常免费}int getCalories() const override {return decoratedCoffee_->getCalories(); // 冰块无热量}void prepare() const override {decoratedCoffee_->prepare();std::string levelDesc;switch(iceLevel_) {case 1: levelDesc = "少量"; break;case 2: levelDesc = "适量"; break;case 3: levelDesc = "大量"; break;}std::cout << "🧊 加入 " << levelDesc << " 冰块" << std::endl;}std::unique_ptr<Coffee> clone() const override {auto clonedBase = decoratedCoffee_->clone();return std::make_unique<IceDecorator>(std::move(clonedBase), iceLevel_);}// 冰特有方法void adjustIceLevel(int level) {iceLevel_ = std::clamp(level, 1, 3);std::cout << "🎛️ 调整冰块等级: " << iceLevel_ << std::endl;}
};
UML 武功秘籍图
实战演练:武器附魔系统
#include <map>
#include <algorithm>// 更复杂的装饰器模式应用:游戏武器附魔系统// 组件接口:武器
class Weapon {
public:virtual ~Weapon() = default;virtual std::string getName() const = 0;virtual std::string getDescription() const = 0;virtual int getBaseDamage() const = 0;virtual int getTotalDamage() const = 0;virtual std::string getDamageType() const = 0;virtual void attack() const = 0;virtual std::unique_ptr<Weapon> clone() const = 0;
};// 具体组件:基础武器
class BaseWeapon : public Weapon {
protected:std::string name_;std::string description_;int baseDamage_;std::string damageType_;public:BaseWeapon(const std::string& name, const std::string& description, int damage, const std::string& damageType = "物理"): name_(name), description_(description), baseDamage_(damage), damageType_(damageType) {}std::string getName() const override {return name_;}std::string getDescription() const override {return description_;}int getBaseDamage() const override {return baseDamage_;}int getTotalDamage() const override {return baseDamage_;}std::string getDamageType() const override {return damageType_;}void attack() const override {std::cout << "⚔️ 使用 " << name_ << " 攻击! 造成 " << getTotalDamage() << " 点" << damageType_ << "伤害" << std::endl;}std::unique_ptr<Weapon> clone() const override {return std::make_unique<BaseWeapon>(*this);}
};// 武器装饰器基类
class WeaponDecorator : public Weapon {
protected:std::unique_ptr<Weapon> decoratedWeapon_;public:WeaponDecorator(std::unique_ptr<Weapon> weapon) : decoratedWeapon_(std::move(weapon)) {}std::string getName() const override {return decoratedWeapon_->getName();}std::string getDescription() const override {return decoratedWeapon_->getDescription();}int getBaseDamage() const override {return decoratedWeapon_->getBaseDamage();}int getTotalDamage() const override {return decoratedWeapon_->getTotalDamage();}std::string getDamageType() const override {return decoratedWeapon_->getDamageType();}void attack() const override {decoratedWeapon_->attack();}std::unique_ptr<Weapon> clone() const override {auto clonedBase = decoratedWeapon_->clone();return std::make_unique<WeaponDecorator>(std::move(clonedBase));}
};// 具体装饰器:火焰附魔
class FireEnchantment : public WeaponDecorator {
private:int fireDamage_;std::string enchantmentName_;public:FireEnchantment(std::unique_ptr<Weapon> weapon, int damage = 15, const std::string& name = "火焰"): WeaponDecorator(std::move(weapon)), fireDamage_(damage), enchantmentName_(name) {}std::string getName() const override {return decoratedWeapon_->getName() + " [🔥" + enchantmentName_ + "]";}std::string getDescription() const override {return decoratedWeapon_->getDescription() + ",附魔了" + enchantmentName_ + "之力";}int getTotalDamage() const override {return decoratedWeapon_->getTotalDamage() + fireDamage_;}std::string getDamageType() const override {return "火焰";}void attack() const override {std::cout << "🔥 " << getName() << " 燃烧着烈焰!" << std::endl;decoratedWeapon_->attack();std::cout << "💥 额外的火焰伤害: " << fireDamage_ << " 点" << std::endl;}std::unique_ptr<Weapon> clone() const override {auto clonedBase = decoratedWeapon_->clone();return std::make_unique<FireEnchantment>(std::move(clonedBase), fireDamage_, enchantmentName_);}// 火焰附魔特有方法void intensifyFlame(int additionalDamage) {fireDamage_ += additionalDamage;std::cout << "🔥 强化火焰附魔,额外伤害: +" << additionalDamage << std::endl;}
};// 具体装饰器:冰霜附魔
class FrostEnchantment : public WeaponDecorator {
private:int frostDamage_;int slowEffect_; // 减速效果百分比public:FrostEnchantment(std::unique_ptr<Weapon> weapon, int damage = 12, int slow = 30): WeaponDecorator(std::move(weapon)), frostDamage_(damage), slowEffect_(slow) {}std::string getName() const override {return decoratedWeapon_->getName() + " [❄️冰霜]";}std::string getDescription() const override {return decoratedWeapon_->getDescription() + ",散发着冰冷寒气";}int getTotalDamage() const override {return decoratedWeapon_->getTotalDamage() + frostDamage_;}std::string getDamageType() const override {return "冰霜";}void attack() const override {std::cout << "❄️ " << getName() << " 散发着寒气!" << std::endl;decoratedWeapon_->attack();std::cout << "💧 额外的冰霜伤害: " << frostDamage_ << " 点" << std::endl;std::cout << "🐌 减速效果: " << slowEffect_ << "%" << std::endl;}std::unique_ptr<Weapon> clone() const override {auto clonedBase = decoratedWeapon_->clone();return std::make_unique<FrostEnchantment>(std::move(clonedBase), frostDamage_, slowEffect_);}// 冰霜附魔特有方法void freezeSolid() {std::cout = "🧊 发动冰冻效果!目标被冻结一回合" << std::endl;}
};// 具体装饰器:雷电附魔
class LightningEnchantment : public WeaponDecorator {
private:int lightningDamage_;int chainTargets_; // 连锁目标数量public:LightningEnchantment(std::unique_ptr<Weapon> weapon, int damage = 18, int chain = 2): WeaponDecorator(std::move(weapon)), lightningDamage_(damage), chainTargets_(chain) {}std::string getName() const override {return decoratedWeapon_->getName() + " [⚡雷电]";}std::string getDescription() const override {return decoratedWeapon_->getDescription() + ",缠绕着雷电之力";}int getTotalDamage() const override {return decoratedWeapon_->getTotalDamage() + lightningDamage_;}std::string getDamageType() const override {return "雷电";}void attack() const override {std::cout << "⚡ " << getName() << " 迸发着电光!" << std::endl;decoratedWeapon_->attack();std::cout << "💥 额外的雷电伤害: " << lightningDamage_ << " 点" << std::endl;if (chainTargets_ > 1) {std::cout << "🔗 连锁攻击: " << chainTargets_ << " 个额外目标" << std::endl;}}std::unique_ptr<Weapon> clone() const override {auto clonedBase = decoratedWeapon_->clone();return std::make_unique<LightningEnchantment>(std::move(clonedBase), lightningDamage_, chainTargets_);}// 雷电附魔特有方法void increaseChain(int additionalTargets) {chainTargets_ += additionalTargets;std::cout << "⚡ 增强连锁效果,额外目标: +" << additionalTargets << std::endl;}
};// 具体装饰器:吸血附魔
class LifeStealEnchantment : public WeaponDecorator {
private:int lifeStealPercent_; // 吸血百分比public:LifeStealEnchantment(std::unique_ptr<Weapon> weapon, int percent = 20): WeaponDecorator(std::move(weapon)), lifeStealPercent_(percent) {}std::string getName() const override {return decoratedWeapon_->getName() + " [💉吸血]";}std::string getDescription() const override {return decoratedWeapon_->getDescription() + ",能够吸取生命能量";}int getTotalDamage() const override {return decoratedWeapon_->getTotalDamage();}std::string getDamageType() const override {return decoratedWeapon_->getDamageType();}void attack() const override {std::cout << "💉 " << getName() << " 渴望着生命!" << std::endl;decoratedWeapon_->attack();int stolenLife = getTotalDamage() * lifeStealPercent_ / 100;std::cout << "❤️ 生命偷取: " << stolenLife << " 点生命值" << std::endl;}std::unique_ptr<Weapon> clone() const override {auto clonedBase = decoratedWeapon_->clone();return std::make_unique<LifeStealEnchantment>(std::move(clonedBase), lifeStealPercent_);}// 吸血附魔特有方法void increaseLifeSteal(int additionalPercent) {lifeStealPercent_ += additionalPercent;std::cout << "💉 增强吸血效果,吸血比例: +" << additionalPercent << "%" << std::endl;}
};// 具体装饰器:锋利附魔
class SharpnessEnchantment : public WeaponDecorator {
private:int sharpnessBonus_; // 锋利加成public:SharpnessEnchantment(std::unique_ptr<Weapon> weapon, int bonus = 10): WeaponDecorator(std::move(weapon)), sharpnessBonus_(bonus) {}std::string getName() const override {return decoratedWeapon_->getName() + " [🔪锋利]";}std::string getDescription() const override {return decoratedWeapon_->getDescription() + ",刀刃异常锋利";}int getTotalDamage() const override {return decoratedWeapon_->getTotalDamage() + sharpnessBonus_;}std::string getDamageType() const override {return decoratedWeapon_->getDamageType();}void attack() const override {std::cout << "🔪 " << getName() << " 闪烁着寒光!" << std::endl;decoratedWeapon_->attack();std::cout << "✨ 锋利加成: +" << sharpnessBonus_ << " 点伤害" << std::endl;}std::unique_ptr<Weapon> clone() const override {auto clonedBase = decoratedWeapon_->clone();return std::make_unique<SharpnessEnchantment>(std::move(clonedBase), sharpnessBonus_);}// 锋利附魔特有方法void sharpen(int additionalBonus) {sharpnessBonus_ += additionalBonus;std::cout << "🔪 打磨武器,锋利度: +" << additionalBonus << std::endl;}
};
装饰器模式的招式解析
招式一:装饰器链构建器
// 装饰器链构建器:简化装饰器的组合过程
class DecoratorChainBuilder {
private:std::unique_ptr<Coffee> currentCoffee_;public:DecoratorChainBuilder(std::unique_ptr<Coffee> baseCoffee) : currentCoffee_(std::move(baseCoffee)) {}// 咖啡装饰方法DecoratorChainBuilder& addMilk(double cost = 1.5, int calories = 50) {currentCoffee_ = std::make_unique<MilkDecorator>(std::move(currentCoffee_), cost, calories);return *this;}DecoratorChainBuilder& addSugar(int spoons = 1, double cost = 0.5, int calories = 20) {currentCoffee_ = std::make_unique<SugarDecorator>(std::move(currentCoffee_), spoons, cost, calories);return *this;}DecoratorChainBuilder& addCream(double cost = 2.0, int calories = 100) {currentCoffee_ = std::make_unique<CreamDecorator>(std::move(currentCoffee_), cost, calories);return *this;}DecoratorChainBuilder& addSpice(const std::string& spice, double cost = 1.0, int calories = 5) {currentCoffee_ = std::make_unique<SpiceDecorator>(std::move(currentCoffee_), spice, cost, calories);return *this;}DecoratorChainBuilder& addIce(int level = 2) {currentCoffee_ = std::make_unique<IceDecorator>(std::move(currentCoffee_), level);return *this;}// 武器装饰方法DecoratorChainBuilder& addFireEnchantment(int damage = 15, const std::string& name = "火焰") {auto weapon = dynamic_cast<Weapon*>(currentCoffee_.get());if (weapon) {auto weaponPtr = std::unique_ptr<Weapon>(currentCoffee_.release());currentCoffee_ = std::make_unique<FireEnchantment>(std::move(weaponPtr), damage, name);}return *this;}// 获取最终结果std::unique_ptr<Coffee> build() {return std::move(currentCoffee_);}// 创建预设组合static std::unique_ptr<Coffee> createLatte() {return DecoratorChainBuilder(std::make_unique<BasicCoffee>("浓缩咖啡", 3.0, 5)).addMilk(2.0, 60).addSugar(2).build();}static std::unique_ptr<Coffee> createCaramelMacchiato() {return DecoratorChainBuilder(std::make_unique<BasicCoffee>("浓缩咖啡", 3.0, 5)).addMilk().addCaramelSyrup().addCream().build();}static std::unique_ptr<Weapon> createFlamingSword() {auto baseSword = std::make_unique<BaseWeapon>("钢剑", "一把标准的钢制长剑", 25);return std::make_unique<FireEnchantment>(std::move(baseSword), 15, "烈焰");}private:// 辅助方法:焦糖糖浆(示例扩展)DecoratorChainBuilder& addCaramelSyrup(double cost = 1.5, int calories = 80) {// 这里可以创建一个CaramelSyrupDecorator// 简化实现,使用糖装饰器模拟currentCoffee_ = std::make_unique<SugarDecorator>(std::move(currentCoffee_), 2, cost, calories);return *this;}
};
招式二:装饰器管理器
// 装饰器管理器:管理装饰器的注册和应用
class DecoratorManager {
private:std::map<std::string, std::function<std::unique_ptr<Coffee>(std::unique_ptr<Coffee>)>> coffeeDecorators_;std::map<std::string, std::function<std::unique_ptr<Weapon>(std::unique_ptr<Weapon>)>> weaponDecorators_;public:DecoratorManager() {registerDefaultDecorators();}void registerDefaultDecorators() {// 注册咖啡装饰器coffeeDecorators_["milk"] = [](std::unique_ptr<Coffee> coffee) {return std::make_unique<MilkDecorator>(std::move(coffee));};coffeeDecorators_["sugar"] = [](std::unique_ptr<Coffee> coffee) {return std::make_unique<SugarDecorator>(std::move(coffee));};coffeeDecorators_["cream"] = [](std::unique_ptr<Coffee> coffee) {return std::make_unique<CreamDecorator>(std::move(coffee));};coffeeDecorators_["cinnamon"] = [](std::unique_ptr<Coffee> coffee) {return std::make_unique<SpiceDecorator>(std::move(coffee), "肉桂");};coffeeDecorators_["ice"] = [](std::unique_ptr<Coffee> coffee) {return std::make_unique<IceDecorator>(std::move(coffee));};// 注册武器装饰器weaponDecorators_["fire"] = [](std::unique_ptr<Weapon> weapon) {return std::make_unique<FireEnchantment>(std::move(weapon));};weaponDecorators_["frost"] = [](std::unique_ptr<Weapon> weapon) {return std::make_unique<FrostEnchantment>(std::move(weapon));};weaponDecorators_["lightning"] = [](std::unique_ptr<Weapon> weapon) {return std::make_unique<LightningEnchantment>(std::move(weapon));};weaponDecorators_["lifesteal"] = [](std::unique_ptr<Weapon> weapon) {return std::make_unique<LifeStealEnchantment>(std::move(weapon));};weaponDecorators_["sharpness"] = [](std::unique_ptr<Weapon> weapon) {return std::make_unique<SharpnessEnchantment>(std::move(weapon));};}// 应用多个装饰器std::unique_ptr<Coffee> decorateCoffee(std::unique_ptr<Coffee> coffee, const std::vector<std::string>& decorators) {auto result = std::move(coffee);for (const auto& decoratorName : decorators) {auto it = coffeeDecorators_.find(decoratorName);if (it != coffeeDecorators_.end()) {result = it->second(std::move(result));std::cout << "✨ 应用装饰器: " << decoratorName << std::endl;} else {std::cout << "❌ 未知的咖啡装饰器: " << decoratorName << std::endl;}}return result;}std::unique_ptr<Weapon> decorateWeapon(std::unique_ptr<Weapon> weapon,const std::vector<std::string>& enchantments) {auto result = std::move(weapon);for (const auto& enchantmentName : enchantments) {auto it = weaponDecorators_.find(enchantmentName);if (it != weaponDecorators_.end()) {result = it->second(std::move(result));std::cout << "✨ 应用附魔: " << enchantmentName << std::endl;} else {std::cout << "❌ 未知的武器附魔: " << enchantmentName << std::endl;}}return result;}// 获取可用的装饰器列表std::vector<std::string> getAvailableCoffeeDecorators() const {std::vector<std::string> decorators;for (const auto& pair : coffeeDecorators_) {decorators.push_back(pair.first);}return decorators;}std::vector<std::string> getAvailableWeaponEnchantments() const {std::vector<std::string> enchantments;for (const auto& pair : weaponDecorators_) {enchantments.push_back(pair.first);}return enchantments;}// 创建预设配置std::unique_ptr<Coffee> createPresetCoffee(const std::string& presetName) {if (presetName == "latte") {return decorateCoffee(std::make_unique<BasicCoffee>("浓缩咖啡", 3.0, 5),{"milk", "sugar"});} else if (presetName == "iced_coffee") {return decorateCoffee(std::make_unique<BasicCoffee>("美式咖啡", 2.5, 3),{"ice", "sugar"});} else if (presetName == "seasonal_special") {return decorateCoffee(std::make_unique<BasicCoffee>("特调咖啡", 4.0, 10),{"milk", "cream", "cinnamon"});}return nullptr;}
};
完整测试代码
// 测试装饰器模式
void testDecoratorPattern() {std::cout << "=== 装饰器模式测试开始 ===" << std::endl;// 测试咖啡装饰系统std::cout << "\n--- 咖啡装饰系统测试 ---" << std::endl;// 创建基础咖啡auto basicCoffee = std::make_unique<BasicCoffee>("美式咖啡", 2.5, 3);std::cout << "基础咖啡: " << basicCoffee->getDescription() << std::endl;std::cout << "价格: $" << basicCoffee->getCost() << std::endl;std::cout << "热量: " << basicCoffee->getCalories() << " 卡路里" << std::endl;basicCoffee->prepare();// 逐层添加装饰std::cout << "\n🎨 开始装饰咖啡..." << std::endl;auto milkCoffee = std::make_unique<MilkDecorator>(std::move(basicCoffee));std::cout << "添加牛奶后: " << milkCoffee->getDescription() << std::endl;std::cout << "价格: $" << milkCoffee->getCost() << std::endl;auto sugarCoffee = std::make_unique<SugarDecorator>(std::move(milkCoffee), 2);std::cout << "添加糖后: " << sugarCoffee->getDescription() << std::endl;std::cout << "价格: $" << sugarCoffee->getCost() << std::endl;auto creamCoffee = std::make_unique<CreamDecorator>(std::move(sugarCoffee));std::cout << "添加奶油后: " << creamCoffee->getDescription() << std::endl;std::cout << "价格: $" << creamCoffee->getCost() << std::endl;auto finalCoffee = std::make_unique<SpiceDecorator>(std::move(creamCoffee), "肉桂");std::cout << "最终咖啡: " << finalCoffee->getDescription() << std::endl;std::cout << "总价格: $" << finalCoffee->getCost() << std::endl;std::cout << "总热量: " << finalCoffee->getCalories() << " 卡路里" << std::endl;std::cout << "\n🍴 准备最终咖啡:" << std::endl;finalCoffee->prepare();// 测试武器附魔系统std::cout << "\n--- 武器附魔系统测试 ---" << std::endl;// 创建基础武器auto basicSword = std::make_unique<BaseWeapon>("钢剑", "一把标准的钢制长剑", 25);std::cout << "基础武器: " << basicSword->getName() << std::endl;std::cout << "描述: " << basicSword->getDescription() << std::endl;std::cout << "基础伤害: " << basicSword->getBaseDamage() << std::endl;basicSword->attack();// 添加附魔std::cout << "\n🎇 开始附魔武器..." << std::endl;auto fireSword = std::make_unique<FireEnchantment>(std::move(basicSword), 15, "烈焰");std::cout << "火焰附魔后: " << fireSword->getName() << std::endl;std::cout << "描述: " << fireSword->getDescription() << std::endl;std::cout << "总伤害: " << fireSword->getTotalDamage() << std::endl;fireSword->attack();auto frostFireSword = std::make_unique<FrostEnchantment>(std::move(fireSword), 12);std::cout << "\n冰火双附魔后: " << frostFireSword->getName() << std::endl;std::cout << "描述: " << frostFireSword->getDescription() << std::endl;std::cout << "总伤害: " << frostFireSword->getTotalDamage() << std::endl;frostFireSword->attack();auto ultimateSword = std::make_unique<SharpnessEnchantment>(std::move(frostFireSword), 10);std::cout << "\n最终武器: " << ultimateSword->getName() << std::endl;std::cout << "描述: " << ultimateSword->getDescription() << std::endl;std::cout << "总伤害: " << ultimateSword->getTotalDamage() << std::endl;ultimateSword->attack();// 测试装饰器链构建器std::cout << "\n--- 装饰器链构建器测试 ---" << std::endl;auto customCoffee = DecoratorChainBuilder(std::make_unique<BasicCoffee>("浓缩咖啡", 3.0, 5)).addMilk(2.0, 60).addSugar(2).addCream(1.5, 80).addSpice("香草", 0.8, 10).build();std::cout << "定制咖啡: " << customCoffee->getDescription() << std::endl;std::cout << "总价格: $" << customCoffee->getCost() << std::endl;std::cout << "总热量: " << customCoffee->getCalories() << " 卡路里" << std::endl;customCoffee->prepare();// 测试装饰器管理器std::cout << "\n--- 装饰器管理器测试 ---" << std::endl;DecoratorManager manager;auto presetLatte = manager.createPresetCoffee("latte");if (presetLatte) {std::cout << "预设拿铁: " << presetLatte->getDescription() << std::endl;presetLatte->prepare();}// 动态应用多个装饰器auto dynamicCoffee = manager.decorateCoffee(std::make_unique<BasicCoffee>("冷萃咖啡", 3.5, 8),{"ice", "sugar", "cream"});std::cout << "\n动态装饰咖啡: " << dynamicCoffee->getDescription() << std::endl;dynamicCoffee->prepare();// 测试武器动态附魔auto dynamicWeapon = manager.decorateWeapon(std::make_unique<BaseWeapon>("战斧", "一把沉重的双刃战斧", 35),{"fire", "sharpness", "lifesteal"});std::cout << "\n动态附魔武器: " << dynamicWeapon->getName() << std::endl;dynamicWeapon->attack();std::cout << "\n=== 装饰器模式测试结束 ===" << std::endl;
}// 实战应用:咖啡店系统
class CoffeeShopSystem {
private:DecoratorManager decoratorManager_;std::vector<std::unique_ptr<Coffee>> orderHistory_;public:void run() {std::cout << "\n🏪 欢迎来到装饰器咖啡店!" << std::endl;std::cout << "========================" << std::endl;while (true) {std::cout << "\n请选择操作:" << std::endl;std::cout << "1. 点咖啡" << std::endl;std::cout << "2. 查看菜单" << std::endl;std::cout << "3. 查看订单历史" << std::cout << "4. 退出" << std::endl;std::cout << "选择: ";int choice;std::cin >> choice;switch (choice) {case 1:takeOrder();break;case 2:showMenu();break;case 3:showOrderHistory();break;case 4:std::cout << "👋 感谢光临,再见!" << std::endl;return;default:std::cout << "❌ 无效选择" << std::endl;}}}private:void takeOrder() {std::cout << "\n☕ 请选择基础咖啡:" << std::endl;std::cout << "1. 美式咖啡 ($2.5)" << std::endl;std::cout << "2. 浓缩咖啡 ($3.0)" << std::endl;std::cout << "3. 冷萃咖啡 ($3.5)" << std::endl;std::cout << "选择: ";int baseChoice;std::cin >> baseChoice;std::unique_ptr<Coffee> baseCoffee;switch (baseChoice) {case 1:baseCoffee = std::make_unique<BasicCoffee>("美式咖啡", 2.5, 3);break;case 2:baseCoffee = std::make_unique<BasicCoffee>("浓缩咖啡", 3.0, 5);break;case 3:baseCoffee = std::make_unique<BasicCoffee>("冷萃咖啡", 3.5, 8);break;default:std::cout << "❌ 无效选择" << std::endl;return;}std::cout << "\n🎨 请选择添加的配料 (输入0结束):" << std::endl;auto availableDecorators = decoratorManager_.getAvailableCoffeeDecorators();for (size_t i = 0; i < availableDecorators.size(); ++i) {std::cout << i + 1 << ". " << getDecoratorDisplayName(availableDecorators[i]) << std::endl;}std::vector<std::string> selectedDecorators;while (true) {std::cout << "选择配料编号 (0结束): ";int decoratorChoice;std::cin >> decoratorChoice;if (decoratorChoice == 0) break;if (decoratorChoice > 0 && decoratorChoice <= static_cast<int>(availableDecorators.size())) {selectedDecorators.push_back(availableDecorators[decoratorChoice - 1]);std::cout << "✅ 已添加: " << getDecoratorDisplayName(availableDecorators[decoratorChoice - 1]) << std::endl;} else {std::cout << "❌ 无效选择" << std::endl;}}// 应用装饰器auto finalCoffee = decoratorManager_.decorateCoffee(std::move(baseCoffee), selectedDecorators);std::cout << "\n🧾 订单详情:" << std::endl;std::cout << "咖啡: " << finalCoffee->getDescription() << std::endl;std::cout << "价格: $" << finalCoffee->getCost() << std::endl;std::cout << "热量: " << finalCoffee->getCalories() << " 卡路里" << std::endl;std::cout << "\n🍴 制作咖啡..." << std::endl;finalCoffee->prepare();// 保存到历史orderHistory_.push_back(std::move(finalCoffee));std::cout << "✅ 订单完成!" << std::endl;}void showMenu() {std::cout << "\n📋 咖啡店菜单" << std::endl;std::cout << "=============" << std::endl;std::cout << "\n基础咖啡:" << std::endl;std::cout << "1. 美式咖啡 - $2.5 (3 卡路里)" << std::endl;std::cout << "2. 浓缩咖啡 - $3.0 (5 卡路里)" << std::endl;std::cout << "3. 冷萃咖啡 - $3.5 (8 卡路里)" << std::endl;std::cout << "\n可用配料:" << std::endl;auto decorators = decoratorManager_.getAvailableCoffeeDecorators();for (const auto& decorator : decorators) {std::cout << "- " << getDecoratorDisplayName(decorator) << std::endl;}std::cout << "\n推荐组合:" << std::endl;std::cout << "拿铁: 浓缩咖啡 + 牛奶 + 糖" << std::endl;std::cout << "冰咖啡: 美式咖啡 + 冰 + 糖" << std::endl;std::cout << "季节特调: 特调咖啡 + 牛奶 + 奶油 + 肉桂" << std::endl;}void showOrderHistory() {std::cout << "\n📊 订单历史" << std::endl;std::cout << "===========" << std::endl;if (orderHistory_.empty()) {std::cout << "暂无订单历史" << std::endl;return;}double totalRevenue = 0;for (size_t i = 0; i < orderHistory_.size(); ++i) {std::cout << i + 1 << ". " << orderHistory_[i]->getDescription() << " - $" << orderHistory_[i]->getCost() << std::endl;totalRevenue += orderHistory_[i]->getCost();}std::cout << "\n总订单数: " << orderHistory_.size() << std::endl;std::cout << "总收入: $" << totalRevenue << std::endl;}std::string getDecoratorDisplayName(const std::string& decoratorName) {static std::map<std::string, std::string> displayNames = {{"milk", "牛奶 (+$1.5, +50 卡路里)"},{"sugar", "糖 (+$0.5, +20 卡路里/勺)"},{"cream", "奶油 (+$2.0, +100 卡路里)"},{"cinnamon", "肉桂 (+$1.0, +5 卡路里)"},{"ice", "冰 (免费)"}};auto it = displayNames.find(decoratorName);return it != displayNames.end() ? it->second : decoratorName;}
};int main() {testDecoratorPattern();// 运行咖啡店系统示例CoffeeShopSystem coffeeShop;coffeeShop.run();return 0;
}
装饰器模式的武学心得
适用场景
- 动态扩展功能:需要在不修改原有代码的情况下动态地给对象添加功能
- 避免子类爆炸:当使用继承会导致类爆炸性增长时
- 透明性要求:希望客户端代码无需知道对象是否被装饰过
- 撤销功能:需要能够动态地添加和撤销功能时
优点
- 灵活性:比继承更灵活,可以动态添加和撤销功能
- 符合开闭原则:对扩展开放,对修改关闭
- 避免类爆炸:不需要为每种功能组合创建子类
- 职责分离:每个装饰器只关注一个特定的功能
缺点
- 复杂性:会增加很多小类,使系统变得更复杂
- 调试困难:多层装饰可能使调试变得困难
- 初始化复杂:创建高度装饰的对象可能需要很多代码
武林高手的点评
Composite 赞叹道:“Decorator 兄的动态装饰确实精妙!能够如此灵活地扩展对象功能,这在需要动态增强能力时确实无人能及。”
Adapter 也点头称赞:“Decorator 兄专注于功能的透明扩展,而我更关注接口的兼容转换。我们都在不修改原有代码的情况下扩展对象的能力。”
Decorator 谦虚回应:“诸位过奖了。每个模式都有其适用场景。在需要动态添加功能时,我的装饰器模式确实能发挥重要作用。但在需要统一处理层次结构时,Composite 兄的方法更加合适。”
下章预告
在Decorator展示完他的装饰艺术后,Facade 面如冠玉、气质儒雅地走出,他步履从容,向众人微微颔首。
“Decorator 兄的动态装饰确实灵活,但在复杂系统面前,客户端往往需要更简洁的接口。” Facade 温和地说道,“下一章,我将展示如何通过外观模式为复杂子系统提供一个统一的简洁接口!”
架构老人满意地点头:“善!简化复杂系统的接口确实是提升易用性的关键。下一章,就请 Facade 展示他的门面艺术!”
欲知 Facade 如何通过外观模式简化复杂系统接口,且听下回分解!