设计模式【九】:装饰器
伪代码
class DecoratedComponent{
public:
DecoratedComponent();
virtual void method1();
virtual void method2();
};
class Decorator: public DecoratedComponent{
public:
Decorator(DecoratedComponent* d){_decorated = d;}
virtual void method1(){_decorated->method1();}
virtual void method2(){_decorated->method2();}
private:
DecoratedComponent* _decorated;
};
class ConcreteDecorator: public Decorator{
public:
ConcreteDecorator(DecoratedComponent*);
virtual void method1(){
Decorator::method1();
addedMethod1();
}
private:
void addedMethod1();
};
优缺点
优点
- 相比静态继承更加灵活。例如在伪代码中对于method1的重写。
- 避免继承结构中的头重脚轻:功能丰富的类应当在继承树的末梢,而装饰器可以随时随地为被装饰的类添加需要的功能,从而避免定义一个复杂的功能齐全的父类。
缺点
- 一个对象根据需要可能有多个装饰器以实现不同的功能扩展,因此写代码的时候不能假定对象与装饰器的一一对应关系。
- 会产生许多琐碎的对象。
何时使用
- 动态地扩展独立对象的功能。
- 希望扩展的功能可以被撤销。
- 通过继承来扩展功能不合适的时候,比如程序有大量的独立对象,一个类只有一个实例,如果为了扩展功能每个类都搞一个子类,甚至每个功能都搞一个子类,那就太繁琐了。
实现时技巧
- 装饰类的接口与被装饰类的要吻合。
- 如果仅仅为了实现功能扩展,那就没必要搞一个抽象接口类。
- 有时会出现这种情况:对于一个被装饰类,在不同情景下我们进行不同的功能扩展,设计不同的装饰器。那么需要考虑这个公共的被装饰类应当简洁,最小化。
- 换皮还是换核?我们可以使用装饰器对功能进行“换皮”,但如果我们直接改变被装饰类,一样可以实现功能的扩展或修改,也就是“换核”。二者各有利弊,还是trade off。