原文地址:http://www.jellythink.com/archives/171
前言
在实际开发时,你有没有碰到过这种问题;开发一个类,封装了一个对象的核心操作,而这些操作就是客户使用该类时都会去调用的操作;而有一些非核心的操作,可能会使用,也可能不会使用;现在该怎么办呢?
- 将这些非核心的操作全部放到类中,这样,一个类就包含了很多核心的操作和一些看似有关,但是又无关的操作;这就会使核心类发生“爆炸”的现象,从而使核心类失去了一定的价值,也使使用核心类的客户在核心操作和非核心操作中挣扎;
- 使用继承来扩展核心类,需要使用核心类时,直接建立核心类对象;当需要使用核心类扩展类时,就建立核心类扩展类对象;这样貌似是一种很有效的方法;但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;同时,又掉入了另一个陷阱,随着扩展功能的增多,子类也会增多,各种子类的组合,就会导致类的膨胀,最后,就会被淹没在类的海洋;此时,也不用我多说,你是不是想起了桥接模式,桥接模式就是为了适应多个维度的变化而发生子类“爆炸”的情况,但是,桥接模式是为了适应抽象和实现的不同变化,并不适用于我这里说的。那如何是好,这就要说到今天总结的装饰模式了。
什么是装饰模式?
在GOF的《设计模式:可复用面向对象软件的基础》一书中对装饰模式是这样说的:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。通常给对象添加功能,要么直接修改对象添加相应的功能,要么派生对应的子类来扩展,抑或是使用对象组合的方式。显然,直接修改对应的类这种方式并不可取。在面向对象的设计中,而我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式,可以很灵活的给对象添加所需要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。总之,装饰模式是通过把复杂的功能简单化,分散化,然后再运行期间,根据需要来动态组合的这样一个模式。它使得我们可以给某个对象而不是整个类添加一些功能。
UML类图
Component:定义一个对象接口,可以给这些对象动态地添加职责;
ConcreteComponent:定义一个具体的Component,继承自Component,重写了Component类的虚函数;
Decorator:维持一个指向Component对象的指针,该指针指向需要被装饰的对象;并定义一个与Component接口一致的接口;
ConcreteDecorator:向组件添加职责。
代码实现
1 /* 2 ** FileName : DecoratorPatternDemo 3 ** Author : Jelly Young 4 ** Date : 2013/12/19 5 ** Description : More information, please go to http://www.jellythink.com 6 */ 7 #include <iostream> 8 using namespace std; 9 class Component 10 { 11 public: 12 virtual void Operation() = 0; 13 }; 14 class ConcreteComponent : public Component 15 { 16 public: 17 void Operation() 18 { 19 cout<<"I am no decoratored ConcreteComponent"<<endl; 20 } 21 }; 22 class Decorator : public Component 23 { 24 public: 25 Decorator(Component *pComponent) : m_pComponentObj(pComponent) {} 26 void Operation() 27 { 28 if (m_pComponentObj != NULL) 29 { 30 m_pComponentObj->Operation(); 31 } 32 } 33 protected: 34 Component *m_pComponentObj; 35 }; 36 class ConcreteDecoratorA : public Decorator 37 { 38 public: 39 ConcreteDecoratorA(Component *pDecorator) : Decorator(pDecorator){} 40 void Operation() 41 { 42 AddedBehavior(); 43 Decorator::Operation(); 44 } 45 void AddedBehavior() 46 { 47 cout<<"This is added behavior A."<<endl; 48 } 49 }; 50 class ConcreteDecoratorB : public Decorator 51 { 52 public: 53 ConcreteDecoratorB(Component *pDecorator) : Decorator(pDecorator){} 54 void Operation() 55 { 56 AddedBehavior(); 57 Decorator::Operation(); 58 } 59 void AddedBehavior() 60 { 61 cout<<"This is added behavior B."<<endl; 62 } 63 }; 64 int main() 65 { 66 Component *pComponentObj = new ConcreteComponent(); 67 Decorator *pDecoratorAOjb = new ConcreteDecoratorA(pComponentObj); 68 pDecoratorAOjb->Operation(); 69 cout<<"============================================="<<endl; 70 Decorator *pDecoratorBOjb = new ConcreteDecoratorB(pComponentObj); 71 pDecoratorBOjb->Operation(); 72 cout<<"============================================="<<endl; 73 Decorator *pDecoratorBAOjb = new ConcreteDecoratorB(pDecoratorAOjb); 74 pDecoratorBAOjb->Operation(); 75 cout<<"============================================="<<endl; 76 delete pDecoratorBAOjb; 77 pDecoratorBAOjb = NULL; 78 delete pDecoratorBOjb; 79 pDecoratorBOjb = NULL; 80 delete pDecoratorAOjb; 81 pDecoratorAOjb = NULL; 82 delete pComponentObj; 83 pComponentObj = NULL; 84 }