【转】设计模式学习笔记(9)-装饰
装饰(Decorator)模式和Adapter、Composite模式有点像,但目的则不同。现在我们看来如果为一个类增加职责,有两种方案,继承和组合。让子类继承父类并扩展父类的功能。但是这种方式有很大缺陷,它是静态的,即在编译时就决定的;另外如果有大量不同的对象,用这种方法会产生子类爆炸,不利于系统的编写与维护。今天要讲的装饰模式就是为了解决这个问题的,它的意图就是:动态地给一个对象添加一些额外的职责。
考虑这样一个例子,我们有一张信纸(Paper),这张纸是空白的,如果要是N张信纸需要装订起来,如果信纸都一样那比较好办,直接new N个paper对象。然而市场上有一种很花哨的笔记本,每张页面都不一样,有很多装饰性的图案。这时直接new 就不行了,如果用子类呢?每一页都是一个子类,貌似开销太大,而且也不够灵活。我们想一下整整工厂里是怎样制作的。工厂里先制作一个基本的Paper,类似于毛坯房,然后交给各个处理机器将装饰性图案印上去。我们的软件设计能不能这样做呢?这就是装饰模式。我们来详细设计一下:
有一个Paper抽象类,它有两个子类:BasicPaper和Decorator,分别表示基本纸张和装饰元素。然后Decorator有几个简单的实现类:
Decorator中的draw方法直接调用component的draw方法
代码实现:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
class Paper {public: virtual string draw() = 0;};class BasicPaper : public Paper{public: string draw() { return "This is a basic paper"; }};class Decorator : public Paper {private: Paper* _paper;public: Decorator(Paper* paper) : _paper(paper) {} string draw() { return _paper->draw(); }};class LineDecorator : public Decorator {public: LineDecorator(Paper* paper) : Decorator(paper) {} string draw() { return Decorator::draw() + ", with linedecorator"; }};class BorderDecorator : public Decorator {public: BorderDecorator(Paper* paper) : Decorator(paper) {} string draw() { return Decorator::draw() + ", with borderdecorator"; }}; |
在上面的代码中Paper中有个draw方法,它返回一个字符串,而子类Decorator都返回with xxx的字符串。
主方法里这样写:
|
1
2
|
Paper* paper = new LineDecorator(new BorderDecorator(new BasicPaper));cout << paper->draw() << endl; |
是不是很奇特?再new的时候我们层层嵌套,这样就保证了paper是一个拥有多项职责的的对象。而且这个对象是独一无二的,是运行时生成的。输出的结果如下:
|
1
|
This is a basic paper, with borderdecorator, with linedecorator |
结果是很完美的,最终的字符串整合符合我们的要求。
如果我们要加两层linedecorator呢?也很简单,改成:
|
1
|
Paper* paper = new LineDecorator(new LineDecorator(new BorderDecorator(new BasicPaper))); |
从上面的例子中可以看出Decorator模式非常灵活,类似于组合模式,它也是动态生成对象,并且逐步为对象添加职责,甚至是无限的职责。
使用Decorator模式有最重要的一点:保持接口的一致性,上面的例子中所有的类都继承于Paper,这样就保持则使用这些对象的统一性,对客户来说这些都是透明的。
最后来看一下Decorator模式的适用性:
- 在不影响其它对象的情况下,以动态、透明的方式给单个对象添加职责
- 处理那些可以撤销的职责
- 当不能采用生成子类的方法进行扩充时
Decorator模式的使用范围主要体现在图形界面设计和数据流。在GUI设计中,可以为一个界面元素添加不同的标识,而在流中为了统一流的操作接口往往也是用Decorator,这点在Java程序设计中十分常见。
转自:http://lecoding.com/articles/196.html
posted on 2013-03-05 14:51 TheKingOfKingFish 阅读(117) 评论(0) 收藏 举报
浙公网安备 33010602011771号