1、描述
装饰是一种结构型模式,允许你通过将对象放入特殊封装对象中来为原对象增加新的行为。由于目标对象和装饰器遵循同一接口,因此你可用装饰来对对象进行无限次的封装。结果对象将获得所有封装器叠加而来的行为。
优点:装饰类和被装饰类都可以独立发展,而不会相互耦合。换句话说,Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此。
缺点:对于装饰模式记住一点就足够了:多层的装饰是比较复杂的。为什么会复杂呢?你想想看,就像剥洋葱一样,你剥到最后才发现是最里层的装饰出现了问题,想象一下工作量,因此,尽量减少装饰类的数量,以便降低系统的复杂度。
2、结构图
- 部件(Component)声明封装器和被封装对象的公用接口。
- 具体部件(ConcreteComponent)类是被封装对象所属的类,它定义了基础行为,但装饰类可以改变这些行为。
- 基础装饰(Decorator)类拥有一个指向被封装对象的引用成员变量。该变量的类型应当被声明为通用部件接口,这样它就可以引用具体的部件和装饰。装饰基类会将所有操作委派给被封装的对象。
- 具体装饰类(Concrete Decorators)定义了可动态添加到部件的额外行为。具体装饰类会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为。
3、C++代码
#include <string>
#include <iostream>
//基础组件接口定义了可以被装饰器修改的操作
class Component {
public:
virtual ~Component() {}
virtual std::string Operation() const = 0;
};
//具体组件提供了操作的默认实现。这些类在程序中可能会有几个变体
class ConcreteComponent : public Component {
public:
std::string Operation() const override {
return "ConcreteComponent";
}
};
//装饰器基类和其他组件遵循相同的接口。这个类的主要目的是为所有的具体装饰器定义封装接口。
//封装的默认实现代码中可能会包含一个保存被封装组件的成员变量,并且负责对齐进行初始化
class Decorator : public Component {
protected:
Component* component_;
public:
Decorator(Component* component) : component_(component) {
}
//装饰器会将所有的工作分派给被封装的组件
std::string Operation() const override {
return this->component_->Operation();
}
};
//具体装饰器必须在被封装对象上调用方法,不过也可以自行在结果中添加一些内容。
class ConcreteDecoratorA : public Decorator {
//装饰器可以调用父类的是实现,来替代直接调用组件方法。
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
}
};
//装饰器可以在调用封装的组件对象的方法前后执行自己的方法
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
}
};
//客户端代码可以使用组件接口来操作所有的具体对象。这种方式可以使客户端和具体的实现类脱耦
void ClientCode(Component* component) {
// ...
std::cout << "RESULT: " << component->Operation();
// ...
}
int main() {
Component* simple = new ConcreteComponent;
std::cout << "Client: I've got a simple component:\n";
ClientCode(simple);
std::cout << "\n\n";
Component* decorator1 = new ConcreteDecoratorA(simple);
Component* decorator2 = new ConcreteDecoratorB(decorator1);
std::cout << "Client: Now I've got a decorated component:\n";
ClientCode(decorator2);
std::cout << "\n";
delete simple;
delete decorator1;
delete decorator2;
return 0;
}
参考