7,装饰者模式(Decorator Pattern)动态的给一个对象添加一些额外的职责。就增加功能来说,此模式比生成子类更为灵活。继承关系的一个替换方案。

装饰( Decorator )模式又叫做包装模式。通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案。

装饰模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。

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

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

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

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

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

实例一

  1 #include <string>
  2 #include <iostream>
  3 #include <memory>
  4 using namespace std;
  5
  6 //抽象类Tank  抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
  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  具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
 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  具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
 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   装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
 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  //   具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任 红外线Infrared 。
 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  //  具体装饰 水路两栖Amphibian
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 #include <iostream>
 2 using namespace std;
 3
 4 class Car
 5 {
 6 public:
 7     virtual void show() = 0;
 8 };
 9
10 class RunCar : public Car
11 {
12 public:
13     virtual void show()
14     {
15         cout << "可以跑" << endl;
16     }
17 protected:
18 private:
19 };
20
21
22 class SwimCarDirector : public Car
23 {
24 public:
25     SwimCarDirector(Car *car)
26     {
27         m_car = car;
28     }
29     void swim()
30     {
31         cout << "可以游" << endl;
32     }
33     virtual void show()
34     {
35         m_car->show();
36         swim();
37     }
38 protected:
39 private:
40     Car *m_car;
41 };
42
43 class  FlyCarDirector : public Car
44 {
45 public:
46     FlyCarDirector(Car *car)
47     {
48         m_car = car;
49     }
50     void fly()
51     {
52         cout << "可以飞" << endl;
53     }
54     virtual void show()
55     {
56         m_car->show();
57         fly();
58     }
59
60 private:
61     Car *m_car;
62 };
63
64 void main()
65 {
66     Car * mycar = NULL;
67     mycar = new RunCar;
68     printf("-----000\n");
69     mycar->show();
70
71     printf("-----aaa\n");
72
73     FlyCarDirector *flycar = new FlyCarDirector(mycar);
74     flycar->show();
75
76     printf("-----bbb\n");
77     SwimCarDirector *swimcar = new SwimCarDirector(flycar);
78     swimcar->show();
79
80     delete swimcar;
81     delete flycar;
82     delete mycar;
83     system("pause");
84     return ;
85 }

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

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

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

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

要点:

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

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

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

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

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

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

适用场景与优缺点:

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

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

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

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

优点:

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

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

缺点:

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

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

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

时间: 2024-10-28 18:54:17

7,装饰者模式(Decorator Pattern)动态的给一个对象添加一些额外的职责。就增加功能来说,此模式比生成子类更为灵活。继承关系的一个替换方案。的相关文章

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

装饰者模式(Decorator Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者模式(Decorator Pattern):动态地将责任附加到对象上. 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案. 使用方法: 1. 首先创建组件(Component)父类, 所有类,具体组件(Concrete Component)和装饰者(Decorator)都属于这一类型, 可以进行扩展

设计模式 - 装饰者模式(Decorator Pattern) 具体解释

装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者模式(Decorator Pattern):动态地将责任附加到对象上. 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案. 用法: 1. 首先创建组件(Component)父类, 全部类,详细组件(Concrete Component)和装饰者(Decorator)都属于这一类型, 能够进行扩展

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

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(结构型)之组合模式(Composite Pattern)>http://blog.csdn.net/yanbober/article/details/45392513 概述 装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为.装饰模式是一种用于替代继承

例说装饰者模式(Decorator Pattern)

前言 装饰者模式在餐饮行业有着比较广泛的应用,网上大部分关于该模式的例子都和饮食相关,以前看译制片电影,每当看到老外们在咖啡店一口流利的点咖啡要加糖要加奶昔要加这加那的时候,感觉好有派~好高大上啊~,为啥我在小卖部都是"来瓶汽水"就没话说了呢~,难道是我不会"装"? 官方定义 动态的给一个对象添加一些职责,就增加功能来说,该模式比生成子类更为灵活--GOF Decorator模式是一种相对简单的对象结构性模式,动态和对象是个对应的关系,正如静态和类这样的对应关系,编

设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 使用方法

装饰者模式(Decorator Pattern) Java的IO类 使用方法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716823 装饰者模式(decorator pattern)参见: http://blog.csdn.net/caroline_wendy/article/details/26707033 Java的IO类使用装饰者模式进行扩展, 其中FilterInputStream类, 就是装饰者(decora

设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法

装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716823 装饰者模式(decorator pattern)參见: http://blog.csdn.net/caroline_wendy/article/details/26707033 Java的IO类使用装饰者模式进行扩展, 当中FilterInputStream类, 就是装饰者(decorato

23种设计模式之装饰器模式(Decorator Pattern)

装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 通过采用组合.而非继承的手法,Decorator模式实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能.避免了单独使用继承带来的“灵活性差"和"多子类衍生问题". 优点:装饰类和被装饰类可以独立发

用最简单的例子理解装饰器模式(Decorator Pattern)

假设有一个公司要做产品套餐,即把不同的产品组合在一起,不同的组合对应不同的价格.最终呈现出来的效果是:把产品组合的所有元素呈现出来,并显示该组合的价格. 每个产品都有名称和价格,首先设计一个关于产品的抽象基类. public abstract class ProductBase { public abstract string GetName(); public abstract double GetPrice(); } 所有的产品都必须继承这个基类,比如家居用品.电器产品等,把这些具体的产品提

php装饰器模式(decorator pattern)

十一点了. <?php /* The decorator pattern allows behavior to be added to an individual object instance, without affecting the behavior of other instances of the same class. We can define multiple decorators, where each adds new functionality. */ interface