文章目录
- 意图
- 什么时候使用装饰
- 真实世界类比
- 装饰模式的实现
- 装饰模式的优缺点
亦称: 装饰者模式、装饰器模式、Wrapper、Decorator
意图
装饰者模式(Decorator Pattern)允许向一个现有的对象扩展新的功能,同时不改变其结构。主要解决直接继承下因功能的不断横向扩展导致子类膨胀的问题,无需考虑子类的维护。
什么时候使用装饰
1、需要大量的子类为某一个对象进行职责增强的时候,可以使用装饰器模式
2、希望使用继承对于类进行动态扩展的时候,可以考虑使用装饰器模式
真实世界类比
穿上多件衣服将获得组合性的效果。
穿衣服是使用装饰的一个例子。 觉得冷时, 你可以穿一件毛衣。 如果穿毛衣还觉得冷, 你可以再套上一件夹克。 如果遇到下雨, 你还可以再穿一件雨衣。 所有这些衣物都 “扩展” 了你的基本行为, 但它们并不是你的一部分, 如果你不再需要某件衣物, 可以方便地随时脱掉。
装饰模式的实现
1、确保业务逻辑可用一个基本组件及多个额外可选层次表示。
2、找出基本组件和可选层次的通用方法。 创建一个组件接口并在其中声明这些方法。
3、创建一个具体组件类, 并定义其基础行为。
4、创建装饰基类, 使用一个成员变量存储指向被封装对象的引用。 该成员变量必须被声明为组件接口类型, 从而能在运行时连接具体组件和装饰。 装饰基类必须将所有工作委派给被封装的对象。
5、确保所有类实现组件接口。
6、将装饰基类扩展为具体装饰。 具体装饰必须在调用父类方法 (总是委派给被封装对象) 之前或之后执行自身的行为。
7、客户端代码负责创建装饰并将其组合成客户端所需的形式。
class Component {
public:
virtual ~Component() {}
virtual std::string Operation() const = 0;
};
/**
* Concrete Components provide default implementations of the operations. There
* might be several variations of these classes.
*/
class ConcreteComponent : public Component {
public:
std::string Operation() const override {
return "ConcreteComponent";
}
};
/**
* The base Decorator class follows the same interface as the other components.
* The primary purpose of this class is to define the wrapping interface for all
* concrete decorators. The default implementation of the wrapping code might
* include a field for storing a wrapped component and the means to initialize
* it.
*/
class Decorator : public Component {
/**
* @var Component
*/
protected:
Component* component_;
public:
Decorator(Component* component) : component_(component) {
}
/**
* The Decorator delegates all work to the wrapped component.
*/
std::string Operation() const override {
return this->component_->Operation();
}
};
/**
* Concrete Decorators call the wrapped object and alter its result in some way.
*/
class ConcreteDecoratorA : public Decorator {
/**
* Decorators may call parent implementation of the operation, instead of
* calling the wrapped object directly. This approach simplifies extension of
* decorator classes.
*/
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
}
};
/**
* Decorators can execute their behavior either before or after the call to a
* wrapped object.
*/
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
}
};
装饰模式的优缺点
优点 | 缺点 |
---|---|
无需创建新子类即可扩展对象的行为 | 在封装器栈中删除特定封装器比较困难 |
可以在运行时添加或删除对象的功能 | 实现行为不受装饰栈顺序影响的装饰比较困难 |
可以用多个装饰封装对象来组合几种行为 | 各层的初始化配置代码看上去可能会很糟糕 |
单一职责原则。 可以将实现了许多不同行为的一个大类拆分为多个较小的类 |