设计模式之装饰模式

1 核心定义

装饰模式是一种结构型设计模式,它允许在不改变现有对象结构的情况下,动态地给该对象添加一些额外的职责。装饰模式通过创建包装对象(装饰器)来包裹真实对象,提供了比继承更有弹性的替代方案。

2 核心思想

继承的替代方案:提供比继承更灵活的扩展方式

开闭原则:对扩展开放,对修改封闭

动态性:可以在运行时动态添加或撤销功能

透明性:装饰对象和真实对象具有相同的接口

3 结构组成

Component(组件接口):定义对象接口,可动态添加职责

ConcreteComponent(具体组件):实现组件接口的具体对象

Decorator(装饰器抽象类):持有一个组件引用,实现组件接口

ConcreteDecorator(具体装饰器):向组件添加具体职责

4 应用场景举例

以咖啡订单系统为例,假设我们需要计算不同咖啡饮品的价格和描述:

基础咖啡:浓缩咖啡、美式咖啡

配料:牛奶、摩卡、奶油等

顾客可以自由组合基础咖啡和配料

5 UML

6 c++ 代码实现

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 抽象组件:咖啡接口
class Coffee {
public:
    virtual ~Coffee() = default;
    virtual string getDescription() const = 0;
    virtual double cost() const = 0;
};

// 具体组件:浓缩咖啡
class Espresso : public Coffee {
public:
    string getDescription() const override {
        return "浓缩咖啡";
    }
    
    double cost() const override {
        return 25.0;  // 基础价格25元
    }
};

// 具体组件:美式咖啡
class Americano : public Coffee {
public:
    string getDescription() const override {
        return "美式咖啡";
    }
    
    double cost() const override {
        return 20.0;  // 基础价格20元
    }
};

// 抽象装饰器:配料装饰器
class CoffeeDecorator : public Coffee {
protected:
    Coffee* coffee;  // 持有的被装饰对象
    
public:
    CoffeeDecorator(Coffee* c) : coffee(c) {}
    
    string getDescription() const override {
        return coffee->getDescription();
    }
    
    double cost() const override {
        return coffee->cost();
    }
    
    virtual ~CoffeeDecorator() {
        delete coffee;
    }
};

// 具体装饰器:牛奶
class Milk : public CoffeeDecorator {
public:
    Milk(Coffee* c) : CoffeeDecorator(c) {}
    
    string getDescription() const override {
        return coffee->getDescription() + " + 牛奶";
    }
    
    double cost() const override {
        return coffee->cost() + 5.0;  // 牛奶加5元
    }
};

// 具体装饰器:摩卡
class Mocha : public CoffeeDecorator {
public:
    Mocha(Coffee* c) : CoffeeDecorator(c) {}
    
    string getDescription() const override {
        return coffee->getDescription() + " + 摩卡";
    }
    
    double cost() const override {
        return coffee->cost() + 8.0;  // 摩卡加8元
    }
};

// 具体装饰器:奶油
class Whip : public CoffeeDecorator {
public:
    Whip(Coffee* c) : CoffeeDecorator(c) {}
    
    string getDescription() const override {
        return coffee->getDescription() + " + 奶油";
    }
    
    double cost() const override {
        return coffee->cost() + 6.0;  // 奶油加6元
    }
};

// 客户端代码
int main() {
    // 点一杯浓缩咖啡加牛奶和摩卡
    Coffee* coffee = new Espresso();
    coffee = new Milk(coffee);
    coffee = new Mocha(coffee);
    
    cout << "订单: " << coffee->getDescription() << endl;
    cout << "价格: " << coffee->cost() << "元" << endl;
    
    delete coffee;
    return 0;
}

7 总结

如果不使用装饰模式,可能会有以下几种实现方式

方式1:使用继承(每个组合创建一个子类)

cpp 复制代码
// 问题:类爆炸
class EspressoWithMilk : public Espresso { /* ... */ };
class EspressoWithMocha : public Espresso { /* ... */ };
class EspressoWithMilkAndMocha : public Espresso { /* ... */ };
class AmericanoWithMilk : public Americano { /* ... */ };
// ... 需要为每种组合创建类,如果有3种基础咖啡和5种配料,就需要3*2^5=96个类!

方式2:使用属性标志

cpp 复制代码
class Coffee {
private:
    bool hasMilk;
    bool hasMocha;
    bool hasWhip;
    // ... 需要为每种配料添加标志
    
public:
    double cost() {
        double total = basePrice;
        if (hasMilk) total += 5;
        if (hasMocha) total += 8;
        if (hasWhip) total += 6;
        return total;
    }
};

主要问题:

1 违反开闭原则:每次添加新的配料都需要修改Coffee类

2 代码臃肿:类的职责过重,包含所有配料的逻辑

3 维护困难:添加新配料需要修改现有代码,容易引入bug

4 灵活性差:无法动态改变配料组合,配料的组合在编译时就固定了

5 代码重复:如果配料的价格计算逻辑复杂,不同咖啡类中会有重复代码

装饰模式的优势

1 灵活扩展:可以在不修改现有代码的情况下添加新功能

2 组合自由:可以在运行时自由组合不同的装饰器

3 符合单一职责:每个装饰器只负责一个特定的功能

4 避免类爆炸:不需要为每个组合创建新的子类

5 可撤销:可以动态地添加或移除装饰器

装饰模式通过将复杂的功能分解为简单的小功能,并通过组合的方式实现复杂功能,是一种非常灵活的代码组织方式。

相关推荐
c萱3 小时前
AI产品经理——01基础认知篇
设计模式·prompt·aigc·产品经理·ai编程·gitcode·ai-native
YYYing.4 小时前
【设计模式系列 (八) 】组合模式
c++·后端·设计模式·组合模式·c/c++
geovindu18 小时前
rust: Composite Pattern
开发语言·后端·设计模式·rust·组合模式
YYYing.1 天前
【设计模式系列 (七) 】桥接模式
c++·后端·设计模式·桥接模式
阿狗童鞋2 天前
设计模式实战指南
设计模式
电子科技圈2 天前
基于车载SerDes和OpenGMSL协议的SoC设计与验证:行业高频问题解析
设计模式·车载系统·软件构建·设计规范
ClinicTech2 天前
高速冷冻离心机的温控系统与安全保护逻辑解析
设计模式·架构·健康医疗·设计语言
GISMagic2 天前
3.《设计模式》:软件设计与解耦能力提炼
设计模式·ai coding
染指11102 天前
131.Agent-Agent设计模式-MAS多智能体系统(Multi-Agent-System)
人工智能·设计模式·langchain·agent·agents
ShyanZh3 天前
【Python3基础】13-Python 常用设计模式
开发语言·python·设计模式