我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)

转载 2015年07月09日 22:03:38


解决的问题:

我们在装饰新家的时候买了几幅抽象画,买回来之后发现有些加上色彩艳丽的边框更适合我们,而有的加上玻璃罩之后更能符合我们的使用。那我们来怎么解决这个问题呢?他需要动态的给别的对象增加额外的职责,这就是装饰者模式的目的。

我们可以通过继承的方式来给原对象增加新功能,但是装饰者模式采用组合的方式比生成子类更加灵活。


类图及样例实现:


在装饰模式中的各个角色有:

抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。

具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。

装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任。

  1. #include <string>  
  2. #include <iostream>  
  3. #include <memory>  
  4. using namespace std;  
  5.   
  6. //抽象类Tank  
  7. class Tank  
  8. {  
  9. public:  
  10.     virtual void shot()=0;  
  11.     virtual void run()=0;  
  12.   
  13. public:  
  14.     virtual ~Tank()  
  15.     {  
  16.         cout<<"in the destructor of Tank"<<endl;  
  17.     }     
  18. };  
  19. //具体类 T50  
  20. class T50:public Tank  
  21. {  
  22. public:  
  23.     void shot()  
  24.     {  
  25.         cout<<"Tank T50 shot()"<<endl;  
  26.     }  
  27.     void run()  
  28.     {  
  29.         cout<<"Tank T50 run()"<<endl;  
  30.     }  
  31. public:  
  32.     virtual ~T50()  
  33.     {  
  34.         cout<<"In the destructor of T50"<<endl;  
  35.     }  
  36. };  
  37. //具体类T75  
  38. class T75:public Tank  
  39. {  
  40. public:  
  41.     void shot()  
  42.     {  
  43.         cout<<"Tank T75 shot()"<<endl;  
  44.     }  
  45.     void run()  
  46.     {  
  47.         cout<<"Tank T75 run()"<<endl;  
  48.     }  
  49. public:  
  50.     virtual ~T75()  
  51.     {  
  52.         cout<<"In the destructor of T75"<<endl;  
  53.     }  
  54. };  
  55.   
  56. //抽象类,Decorator  
  57. class Decorator:public Tank  
  58. {  
  59. protected:  
  60.     Tank* tank;  
  61. public:  
  62.     Decorator(Tank* tank):tank(tank) {}  //具体的坦克的装饰类  
  63.     virtual ~Decorator()  
  64.     {  
  65.         cout<<"In the destructor of Decorator"<<endl;  
  66.     }  
  67. public:  
  68.     void shot()  
  69.     {  
  70.         tank->shot();  
  71.     }  
  72.     void run()  
  73.     {  
  74.         tank->run();  
  75.     }  
  76. };  
  77.   
  78. class InfraredDecorator: public Decorator  
  79. {  
  80. private:  
  81.     string infrared;//这就是所谓的addAtrribute  
  82. public:  
  83.     InfraredDecorator(Tank* tank):Decorator(tank) {}  
  84.     virtual ~InfraredDecorator()  
  85.     {  
  86.         cout<<"in the destructor of InfraredDecorator"<<endl;  
  87.     }  
  88. public:  
  89.     void set_Infrared(const string &infrared)  
  90.     {  
  91.         this->infrared=infrared;  
  92.     }  
  93.     string get_infrared() const  
  94.     {  
  95.         return infrared;  
  96.     }  
  97.     void run()  
  98.     {  
  99.         tank->run();  
  100.         set_Infrared("+Infrared");  
  101.         cout<<get_infrared()<<endl;  
  102.     }  
  103.     void shot()  
  104.     {  
  105.         tank->shot();  
  106.     }  
  107. };  
  108.   
  109. class AmphibianDecorator:public Decorator  
  110. {  
  111. private:  
  112.     string amphibian;  
  113. public:  
  114.     AmphibianDecorator(Tank* tank):Decorator(tank) {}  
  115.     ~AmphibianDecorator()  
  116.     {  
  117.         cout<<"in the destructor of AmphibianDecorator"<<endl;  
  118.     }  
  119. public:  
  120.     void set_amphibian(const string &hibian)  
  121.     {  
  122.         this->amphibian=hibian;  
  123.     }  
  124.     string get_amphibian() const  
  125.     {  
  126.         return amphibian;  
  127.     }  
  128. public:  
  129.     void run()  
  130.     {  
  131.         tank->run();  
  132.         set_amphibian("+amphibian");  
  133.         cout<<get_amphibian()<<endl;  
  134.     }  
  135.     void shot()  
  136.     {  
  137.         tank->shot();  
  138.     }  
  139. };  
  140.   
  141. int main(int argc, char **argv)  
  142. {  
  143.     //给T50增加红外功能  
  144.     Tank* tank1(new T50);  
  145.     Tank* pid1(new InfraredDecorator(tank1));  
  146.     pid1->shot();  
  147.     cout<<endl;  
  148.     pid1->run();  
  149.     cout<<endl;  
  150.     cout<<endl<<"---------------"<<endl;  
  151.     //给t75增加红外、两栖功能  
  152.     Tank* tank2(new T75);  
  153.     tank2->run();  
  154.     Tank* pid2(new InfraredDecorator(tank2));  
  155.     Tank* pad2(new AmphibianDecorator(pid2));  
  156.     pad2->shot();  
  157.     cout<<endl;  
  158.     pad2->run();  
  159.     cout<<endl;  
  160.     cout<<endl<<"--------------"<<endl;  
  161.   
  162.     //动态撤销其他装饰 ?  
  163.     tank2->run();  
  164.   
  165.     Tank * tank3(tank2);  
  166.     tank3->run();  
  167.     return 0;  
  168. }  


装饰者与适配者模式的区别:

1.关于新职责:适配器也可以在转换时增加新的职责,但主要目的不在此。装饰者模式主要是给被装饰者增加新职责的。

2.关于原接口:适配器模式是用新接口来调用原接口,原接口对新系统是不可见或者说不可用的。装饰者模式原封不动的使用原接口,系统对装饰的对象也通过原接口来完成使用。(增加新接口的装饰者模式可以认为是其变种--“半透明”装饰者)

3.关于其包裹的对象:适配器是知道被适配者的详细情况的(就是那个类或那个接口)。装饰者只知道其接口是什么,至于其具体类型(是基类还是其他派生类)只有在运行期间才知道。


要点:

1. 装饰者和被装饰对象有相同的超类型。

2. 可以用一个或多个装饰者包装一个对象。

3. 装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的。

4. 对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用你喜欢的装饰者来装饰对象。

5. 装饰模式中使用继承的关键是想达到装饰者和被装饰对象的类型匹配,而不是获得其行为。

6. 装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。在实际项目中可以根据需要为装饰者添加新的行为,做到半透明装饰者。


适用场景与优缺点:

在以下情况下应当使用装饰模式:

1.需要扩展一个类的功能,或给一个类增加附加责任。 

2.需要动态地给一个对象增加功能,这些功能可以再动态地撤销。 

3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

优点:

1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:

1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现半透明的装饰者模式。在实际项目中要做出最佳选择。


LCL_data原创于CSDN.NET【http://blog.csdn.net/lcl_data/article/details/8830455

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)

解决的问题: 我们在装饰新家的时候买了几幅抽象画,买回来之后发现有些加上色彩艳丽的边框更适合我们,而有的加上玻璃罩之后更能符合我们的使用。那我们来怎么解决这个问题呢?他需要动态的给别的对象增加额...

我所理解的设计模式(C++实现)——装饰者模式(Decorator Pattern)

解决的问题: 我们在装饰新家的时候买了几幅抽象画,买回来之后发现有些加上色彩艳丽的边框更适合我们,而有的加上玻璃罩之后更能符合我们的使用。那我们来怎么解决这个问题呢?他需要动态的给别的对象增加额外的...

如何让孩子爱上设计模式 ——8.装饰者模式(Decorator Pattern)

如何让孩子爱上设计模式 ——8.装饰者模式(Decorator Pattern)标签: 设计模式初涉描述性文字还记得工厂方法模式小猪开的奶茶店吗?在那一节中讲解的是 通过工厂方法模式来做奶茶,做奶茶...

设计模式初探3——装饰者模式(Decorator Pattern)

装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

设计模式(8)—— 装饰者模式(Decorator Pattern)

我们都知道,可以使用两种方式给一个类或者对象添加行为。         一是使用继承。继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法...

设计模式(结构型)之装饰者模式(Decorator Pattern)

装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。装饰模式是一种用于替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。在装...

设计模式系列之二:装饰者模式(Decorator Pattern)

这一阵还是比较忙,说好的两天一更都达不到,看来自己还是得努力。装饰者模式其实普遍存在于我们的生活抽象中。现存的一些资料是以一个星巴克咖啡店来举例说明的,这里我们就用煎饼果子来举例吧,生动形象。一个煎饼...
  • dxywx
  • dxywx
  • 2015-11-22 20:27
  • 406

设计模式 - 装饰者模式(Decorator Pattern) 详解

装饰者模式(Decorator Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 装饰者模式(Decorator Pattern): ...

设计模式之装饰者模式Decorator Pattern

近来在读《Head first设计模式》这本书,感觉很不错只是书中的代码是用Java写的。因为我熟悉的是C++,于是自己写了C++的例子程序。首先说说我的感受吧,学C++的话,先看《C++ Prime...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)