参考资料
1. 概述
名称:装饰模式,装饰者模式,Wrapper,Decorator
“套娃模式”?
更好地应对对基本功能的多种扩展,动态完成
如何能更加方便地应对多种方法的任意组合?如何在运行时动态的完成,如果使用继承则是静态的,如果可能的组合的很多,子类的数量将很多
通常使用组合的方式实现
生活中的例子:
?UML图
?应用场景
- 希望在运行时为对象新增额外的功能,但是不需要更改设计类的代码,则可以使用装饰模式
- 如果无法通过继承来扩展功能,则也可以考虑使用装饰模式
实现关键:具体装饰必须在调用父类方法之后或者之前执行自身的行为;装饰基类使用一个成员变量指向被装饰对象的引用
装饰模式的优点:
- 无需创建新子类就可以扩展对象的行为
- 可以在运行是添加或者删除对象功能
- 更加符合单一职责原则,比起实现一个复杂的子类,装饰模式更加符合单一职责原则
缺点:
- 初始化代码会比较复杂
- 实现可以任意顺序组合的装饰编码比较困难
一句话总结:装饰模式是一个结构型设计模式,允许你通过将对象放入特殊封装对象来增加新的行为
2. 编码
#include <bits/stdc++.h>
using namespace std;
/**
* 基本成分的接口
*/
class Component {
public:
virtual ~Component() {}
virtual string Operation() const = 0;
};
/**
* 具体成分
*/
class ConcreteComponent : public Component {
public:
string Operation() const override {
return "ConcreteComponent";
}
};
/**
* 基本装饰器,注意实现了基本成分接口
*/
class Decorator : public Component {
protected:
Component* component_;
public:
/**
* @brief 注意这个构造函数
* @param component 基本成分指针
*/
Decorator(Component* component) : component_(component) {}
/**
* @brief 调用基本成分的功能
* @return 基本成分操作返回值
*/
string Operation() const override {
return component_->Operation();
}
};
/**
* 扩展装饰器A
*/
class ConcreteDecoratorA : public Decorator {
public:
/**
* @brief 构造函数会初始化基本装饰器
* @param component 基本成分指针
*/
ConcreteDecoratorA(Component* component) : Decorator(component) {}
/**
* @brief 注意这里也调用了基本装饰器的操作
* @return
*/
string Operation() const override {
return "ConcreteDecortorA(" + Decorator::Operation() + ")";
}
};
/**
* 扩展装饰器B
*/
class ConcreteDecoratorB : public Decorator {
public:
/**
* @brief 构造函数会初始化基本装饰器
* @param component 基本成分指针
*/
ConcreteDecoratorB(Component* component) : Decorator(component) {}
/**
* @brief 注意这里也调用了基本装饰器的操作
* @return
*/
string Operation() const override {
return "ConcreteDecortorB(" + Decorator::Operation() + ")";
}
};
void ClientCode(Component* component) {
cout << "RESULT: " << component->Operation();
}
int main() {
Component* simple = new ConcreteComponent();
cout << "Client: I've got a simple component:\n";
ClientCode(simple);
cout << "\n\n";
Component* decorator1 = new ConcreteDecoratorA(simple);
Component* decorator2 = new ConcreteDecoratorB(decorator1);
cout << "Client: Now I've got a decorated component:\n";
ClientCode(decorator2);
cout << endl;
delete simple;
delete decorator1;
delete decorator2;
return 0;
}
|