原则
- 装饰者和主题继承同一个基类(主要是利用继承来达到“类型匹配”的目的,而不是利用继承获得行为)
- 可以用一个或者多个装饰者包装主体对象
- 装饰者内部保存主体对象的引用或者指针
- 装饰者可以动态的包装主体对象,即运行时改变主体对象行为
经典类图

类图说明:
Component
对象的接口类,定义装饰对象和被装饰对象的共同接口*;
ConcreteComponent
被装饰对象的类定义:属于具体实现的类
Decorator
装饰对象的抽象类,持有一个具体的被修饰对象,并实现接口类继承的公共接口;
ConcreteDecorator
具体的装饰器,负责往被装饰对象添加额外的功能;
精髓
装饰器模式主要是为某个东西附加不同的功能,抽象装饰者和主体继承同一个类(非常关键)。如下例子:
有一块烧饼 (烧饼是主体)
- 夹肉:变成肉夹馍 (夹肉的动作就是装饰)
- 夹菜:变成菜夹馍 (夹菜的动作就是装饰)
其中菜,和肉作为不同的装饰,将馍变成不同口感的食物,抽象来说馍和肉、菜应继承同一个抽象类,它们都是具体的实现。
也可以认为:
- 主体可能只有一个
- 装饰可以有多个,装饰可以任意组合
装饰器的应用场景
- 需要对现有类附加职责,但又不想以继承方式扩充时
- 需要对现有的一组基本功能进行排列组合而产生非常多的功能时
- 当对象的功能需要动态的添加、撤销时
代码实现(咖啡封装)
class Beverage
{
protected:
QString _description = "Unknow";
double _cost = 0;
public:
virtual double cost() const { return _cost; };
virtual QString description() const { return _description; };
};
//装饰者基类
class CondimentDecorator : public Beverage
{
protected:
QSharedPointer<Beverage> _beverage;
public:
CondimentDecorator(QSharedPointer<Beverage>& beverage) : _beverage(beverage)
{
_description = "Decorator";
}
};
//浓咖啡主体
class Espresso : public Beverage
{
public:
Espresso()
{
_description = "Espresso";
_cost = 1.99;
}
};
class Mocha : public CondimentDecorator
{
public:
Mocha(QSharedPointer<Beverage>& beverage) : CondimentDecorator(beverage)
{
_description = "Mocha";
_cost = .99;
}
QString description() const override { return _beverage->description() + _description; }
double cost() const override { return _beverage->cost() + _cost; };
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
{
QSharedPointer<Beverage> coffe(new Espresso());
qDebug() << coffe->description();
qDebug() << coffe->cost();
QSharedPointer<Beverage> mochaCoffe(new Mocha(coffe));
qDebug() << mochaCoffe->description();
qDebug() << mochaCoffe->cost();
}
return a.exec();
}作者:admin 创建时间:2023-12-05 14:33
最后编辑:admin 更新时间:2025-02-10 11:18
最后编辑:admin 更新时间:2025-02-10 11:18