一,装饰器模式简介
装饰器模式是一种结构型设计模式, 它允许在不改变现有对象的情况下,动态地将功能添加到对象中。
装饰器模式是通过创建具有新行为的对象来实现的,这些对象将原始对象进行了包装。
装饰器模式遵循开放/关闭原则,允许开发者在不修改现有代码的情况下添加新的装饰器。
日常开发中常用的装饰器属于类装饰器,通过继承父类来实现。
二,装饰器模式的结构
1.抽象组件(Component):被装饰的对象,声明了对外的统一接口。
2.具体组件(ConcreteComponent):包含抽象组件接口的具体代码实现。
3.抽象装饰器(Decorator):包含对抽象组件的指针或引用,并定义了与抽象组件一致的接口。
4.具体装饰器(ConcreteDecorator):包含抽象装饰器接口的具体代码实现,并且可以在调用对外接口之前或之后添加额外的行为。
对应UML类图:
拿生活中举例:某硬核产品的可拆卸装饰
三,装饰器模式的工作步骤
1.创建抽象组件类,定义抽象组件的对外接口,将核心功能声明在该接口中。
2.创建具体组件类,继承抽象组件类,实现抽象组件类的接口。
3.创建抽象装饰器类,继承抽象组件类,实现抽象组件类的接口,并持有一个抽象组件对象的引用。
4.创建具体装饰器类,继承抽象装饰器类,在实现核心接口之后,添加额外的接口函数。
5.在客户端中使用装饰器包装抽象组件,并调用它们的方法。
四,装饰器模式代码样例
Demo1:
为了简化理解,暂时不带具体装饰器ConcreteDecorator,直接在Decorator中添加额外功能。
代码语言:javascript复制#include <iostream>
class Component {
public:
virtual void operation() = 0;
};
class ConcreteComponent : public Component {
public:
void operation() override {
std::cout << "From ConcreteComponent." << std::endl;
}
};
class Decorator : public Component {
public:
Decorator(Component& component):component_(component){}
void operation() override {
std::cout << "from Decorator." << std::endl;
component_.operation();
}
private:
Component& component_;
};
int main() {
ConcreteComponent concreteComponent;
Decorator decoratedComponent(concreteComponent);
decoratedComponent.operation();
return 0;
}
运行结果:
代码语言:javascript复制from Decorator.
From ConcreteComponent.
五,装饰器模式的应用场景
组件扩展:在大型项目中,随着业务的增加,必定要添加新的功能,装饰器此时可以避免修改原有的基础组件。
API增强:当提供API给第三方进行调用时,装饰器可以用于添加额外的功能,比如日志记录、安全校验等,而调用者无需知道具体的细节。
权限管理:装饰器可以用来控制对原有的特定接口的访问权限。
缓存机制:在网络请求或数据库查询等操作中,装饰器可以用来添加额外的缓存、重试、超时处理等功能。
六,装饰器模式的优缺点
装饰器模式的优点:
1.可以动态地添加或删除对象的功能,无需修改原有的代码。
2.不影响现有对象的结构,符合开闭原则。
3.可以灵活地扩展原有对象的功能。
4.可以使用多个装饰器对象来组合多种功能。
5.使得代码可以根据需要轻松地添加或移除功能。
装饰器模式的缺点:
1.使系统中增加额外的类变量。
2.装饰器对象与原始对象之间的关系过于复杂,降低代码可读性。
七,代码实战
Demo1: 自助冰淇淋制作机
代码语言:javascript复制#include <iostream>
#include <string>
using namespace std;
// Component
class IceCream {
public:
virtual string getDescription() const = 0;
virtual double cost() const = 0;
};
// Concrete Component
class VanillaIceCream : public IceCream {
public:
string getDescription() const override
{
return "Vanilla Ice Cream";
}
double cost() const override { return 160.0; }
};
// Decorator
class Decorator : public IceCream {
protected:
IceCream* iceCream;
public:
Decorator(IceCream* ic)
: iceCream(ic)
{
}
string getDescription() const override
{
return iceCream->getDescription();
}
double cost() const override
{
return iceCream->cost();
}
};
// Concrete Decorator - adds chocolate topping.
class ChocolateDecorator : public Decorator {
public:
ChocolateDecorator(IceCream* ic)
: Decorator(ic)
{
}
string getDescription() const override
{
return iceCream->getDescription()
" with Chocolate";
}
double cost() const override
{
return iceCream->cost() 100.0;
}
};
// Concrete Decorator - adds caramel topping.
class CaramelDecorator : public Decorator {
public:
CaramelDecorator(IceCream* ic)
: Decorator(ic)
{
}
string getDescription() const override
{
return iceCream->getDescription() " with Caramel";
}
double cost() const override
{
return iceCream->cost() 150.0;
}
};
int main()
{
// Create a vanilla ice cream
IceCream* vanillaIceCream = new VanillaIceCream();
cout << "Order: " << vanillaIceCream->getDescription()
<< ", Cost: Rs." << vanillaIceCream->cost()
<< endl;
// Wrap it with ChocolateDecorator
IceCream* chocolateIceCream
= new ChocolateDecorator(vanillaIceCream);
cout << "Order: " << chocolateIceCream->getDescription()
<< ", Cost: Rs." << chocolateIceCream->cost()
<< endl;
// Wrap it with CaramelDecorator
IceCream* caramelIceCream
= new CaramelDecorator(chocolateIceCream);
cout << "Order: " << caramelIceCream->getDescription()
<< ", Cost: Rs." << caramelIceCream->cost()
<< endl;
delete vanillaIceCream;
delete chocolateIceCream;
delete caramelIceCream;
return 0;
}
运行结果:
代码语言:javascript复制Order: Vanilla Ice Cream, Cost: Rs.160
Order: Vanilla Ice Cream with Chocolate, Cost: Rs.260
Order: Vanilla Ice Cream with Chocolate with Caramel, Cost: Rs.410
Demo2: 模拟的绘图组件
代码语言:javascript复制#include <iostream>
using namespace std;
// Component
class Widget
{
public:
virtual void draw() = 0;
};
// Concrete Component
class TextField : public Widget
{
int width, height;
public:
TextField(int w, int h)
{
width = w;
height = h;
}
void draw()
{
cout << "TextField: " << width << "," << height;
}
};
// Decorator
class Decorator : public Widget
{
Widget* wid;
public:
Decorator(Widget* w)
{
wid = w;
}
void draw()
{
wid->draw();
}
};
// Concrete Decorator
class BorderDecorator : public Decorator
{
public:
BorderDecorator(Widget* w): Decorator(w){}
void draw()
{
//基础功能
Decorator::draw();
//扩展功能
cout << "n BorderDecorator" ;
}
};
// Concrete Decorator
class ScrollDecorator : public Decorator
{
public:
ScrollDecorator(Widget* w): Decorator(w){}
/*virtual*/
void draw()
{
//基础功能
Decorator::draw();
//扩展功能
cout << "n ScrollDecorator";
}
};
int main()
{
Widget* aWidget = new BorderDecorator(
new ScrollDecorator(new TextField(80, 24)));
aWidget->draw();
}
运行结果:
代码语言:javascript复制TextField: 80,24
ScrollDecorator
BorderDecorator
八,参考阅读
https://www.pentalog.com/blog/design-patterns/decorator-design-pattern/
https://www.geeksforgeeks.org/introduction-to-decorator-pattern-in-c-design-patterns/
https://sourcemaking.com/design_patterns/decorator/cpp/2
https://sourcemaking.com/design_patterns/decorator