设计模式C++描述----10.装饰(Decorator)模式

一. 举例

我之前做过一个文件系统就叫 MyFileSys 吧,后来的话,客户想加入一些附加功能,比如压缩、加密、杀毒之类的操作,这些附加操作没有先后顺序,比如你可以先压缩再加密,也可以先杀毒再压缩,等等。

这些附加功能是可选的,有的客户要这些功能,有的不要,有的要其中的几种附加功能等等。怎么设计呢?

第一种方案:
直接修改这个独立的文件系统 MyFileSys,对于不同的客户实现不同的文件系统。

后来随着客户的增多,发现维护和修改的工作量越来越大。因为每增加一个客户就要重新生成一个类,然后把客户想要的附加功能加入,更加郁闷的是,只针对一个客户有时也是要修改很多次,客户今天要这些附加功能,明天又想加入另外一些功能,这样改来改去,维护工作量也是很大的。

第二种方案:

后来改用第二种方案,实现一个单独的附加功能类,保持原文件系统不变,这样在客户端就可以轻松的加入一些附加功能。

代码如下:

  1. //定义一个对象接口,可以给这些对象动态地添加职责  
  2. class FileSys  
  3. {  
  4. public:  
  5.     virtual ~FileSys()  
  6.     {  
  7.     }  
  8.   
  9.     virtual void Operation()  
  10.     {  
  11.     }  
  12. protected:  
  13.     FileSys()  
  14.     {  
  15.     }  
  16. };  
  17.   
  18. //定义一个具体的对象  
  19. class MyFileSys:public FileSys  
  20. {  
  21. public:  
  22.     MyFileSys()  
  23.     {  
  24.     }  
  25.   
  26.     ~MyFileSys()  
  27.     {  
  28.     }  
  29.   
  30.     void Operation()  
  31.     {  
  32.         cout<<"MyFileSys operation..."<<endl;  
  33.     }  
  34. };  
  35.   
  36. //装饰抽象类  
  37. class Decorator:public FileSys  
  38. {  
  39. public:  
  40.     Decorator(FileSys* fileSys)  
  41.     {  
  42.         this->_fileSys = fileSys;  
  43.     }  
  44.   
  45.     virtual ~Decorator()  
  46.     {  
  47.         delete _fileSys;  
  48.     }  
  49.   
  50.     void Operation()  
  51.     {  
  52.     }  
  53. protected:  
  54.     FileSys* _fileSys;  
  55. };  
  56.   
  57. //压缩装饰类  
  58. class ZipDecorator:public Decorator  
  59. {  
  60. public:  
  61.     ZipDecorator(FileSys* fileSys):Decorator(fileSys)  
  62.     {  
  63.     }  
  64.   
  65.     ~ZipDecorator()  
  66.     {  
  67.     }  
  68.       
  69.     void Operation()  
  70.     {  
  71.         _fileSys->Operation(); //首先运行以前的功能  
  72.           
  73.         this->AddedZipBehavior(); //附加功能  
  74.     }  
  75.       
  76.     void AddedZipBehavior()  
  77.     {  
  78.         cout<<"Added Zip Behavior...."<<endl;  
  79.     }  
  80. };  
  81.   
  82. //杀毒装饰类  
  83. class KillVirDecorator:public Decorator  
  84. {  
  85. public:  
  86.     KillVirDecorator(FileSys* fileSys):Decorator(fileSys)  
  87.     {  
  88.     }  
  89.       
  90.     ~KillVirDecorator()  
  91.     {  
  92.     }  
  93.       
  94.     void Operation()  
  95.     {  
  96.         _fileSys->Operation();  
  97.           
  98.         this->AddedKillVirBehavior();  
  99.     }  
  100.       
  101.     void AddedKillVirBehavior()  
  102.     {  
  103.         cout<<"Added Kill Virus Behavior...."<<endl;  
  104.     }  
  105. };  
  106.   
  107. //加密装饰类  
  108. class EncryptDecorator:public Decorator  
  109. {  
  110. public:  
  111.     EncryptDecorator(FileSys* fileSys):Decorator(fileSys)  
  112.     {  
  113.     }  
  114.       
  115.     ~EncryptDecorator()  
  116.     {  
  117.     }  
  118.       
  119.     void Operation()  
  120.     {  
  121.         _fileSys->Operation();  
  122.           
  123.         this->AddedEncrypeBehavior();  
  124.     }  
  125.       
  126.     void AddedEncrypeBehavior()  
  127.     {  
  128.         cout<<"Added Encrypt Behavior...."<<endl;  
  129.     }  
  130. };  
  131.   
  132. //////////////////////////////////////////////////////////////////////////  
  133. //测试  
  134. int main()  
  135. {  
  136.     FileSys* fileSys = new MyFileSys();  
  137.       
  138.     Decorator* dec1 = new ZipDecorator(fileSys);  //在原文件系统上,加入压缩功能  
  139.     Decorator* dec2 = new KillVirDecorator(dec1); //在之前的基础上,加入杀毒功能  
  140.     Decorator* dec3 = new EncryptDecorator(dec2); //再加入加密功能  
  141.   
  142.     dec3->Operation();  
  143.   
  144.     return 0;  
  145. }  

这样之后,如果要添加附加功能,实现起来就很方便了。这种模式就是装饰模式。

二. 装饰模式

装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活

说明:

Componet,主要是定义一个接口,通过这个接口可以给这些对象(ConcreteComponent)添加职责。

Dectorator,装饰类,通过外类(ConcreteDecorator)来扩展Component 类的功能,对于Component来说,是无需知道这个抽象类的存在的。

ConcreteDecorator,具体装饰类,添加具体的附加功能。

优点:

1. 装饰类是为已有功能动态地添加更多功能的一种方式。

2. 有效地把类的核心职责装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。

三. 问题讨论

从上图可以看到 Decorator 是继承于 Component 的,也就和 ConcreteComponent 成了兄弟了,但是 Decorator 的作用却是修饰 ConcreteComponent 的,这点好像是很怪怪的!!最说不通的是Decorator 与 Component 是没有is-a关系的!!

我个人觉得:

1. 这个继承关系,不应该是我们要重点关注的。这里使用继承主要是为了要重用 Operation() 这个接口,以达修饰的目的。

2. 重点是 Decorator 与 Component 这个组合关系。装饰类里有一个Component 指针,正是由于它的存在才能修饰到具体的 Component 对象。

posted on 2013-08-09 12:30  any91  阅读(232)  评论(0编辑  收藏  举报