装饰者
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
适用性
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
结构
Component - 定义一个对象接口,可以给这些对象动态地添加职责。
ConcreteComponent - 定义一个对象,可以给这个对象添加一些职责。
Decorator - 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
ConcreteDecorator - 向组件添加职责。
协作:
Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作。
示例情境
有多种不同的咖啡,而每种咖啡又有多种加调料的方式。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| #include <iostream>
class Component { public: virtual void methodA(){} virtual void methodB(){} };
class ConcreteComponent : public Component { public: virtual void methodA() { std::cout<<"I'm methodA from ConcreteComponent."<<std::endl; } virtual void methodB() { std::cout<<"I'm methodB from ConcreteComponent."<<std::endl; } };
class Decorator : public Component {};
class ConcreteDecoratorA : public Decorator { public: ConcreteDecoratorA(Component* comp): Decorator(), m_component(comp){} virtual void methodA() { if (!m_component) return; std::cout<<"I'm methodA called from ConcreteDecoratorA: "<<std::endl; m_component->methodA(); } virtual void methodB() { if (!m_component) return; std::cout<<"I'm methodA called from ConcreteDecoratorB: "<<std::endl; m_component->methodA(); } protected: Component* m_component; };
class ConcreteDecoratorB : public Decorator { public: ConcreteDecoratorB(Component* comp): Decorator(), m_component(comp){} virtual void methodA() { if (!m_component) return; std::cout<<"I'm methodA called from ConcreteDecoratorB: "<<std::endl; m_component->methodA(); } virtual void methodB() { if (!m_component) return; std::cout<<"I'm methodA called from ConcreteDecoratorB: "<<std::endl; m_component->methodA(); } protected: Component* m_component; };
int main() { Component* product_type = new ConcreteComponent(); Component* product = new ConcreteDecoratorA(product_type); product->methodA(); product->methodB(); system("Pause"); }
|
相关模式
- Adapter模式:Decorator模式不同于Adapter模式,因为装饰仅改变对象的职责而不改变它的接口;而适配器将给对象一个全新的接口。
- Composite模式:可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅给对象添加一些额外的职责——它的目的不在于对象聚集。
- Strategy模式:用一个装饰你可以改变对象的外表;而Strategy模式使得你可以改变对象的内核。这是改变对象的两种途径。
[1] 设计模式:可复用面向对象软件的基础
[2] Head First 设计模式