为方便读者,本文已添加至索引:
Decorator(装饰)模式,可以动态地给一个对象添加一些额外的职能。为了更好地理解这个模式,我们将时间线拉回Bridge模式笔记的结尾。那时,白雪公主射出了充满魔法力量的一箭。如好莱坞大片一般,那支飞出的箭矢散发出各种你能想到的美丽光芒。当然,我不会告诉你那支箭华华丽丽地射偏了。因为我们这次更关心这绚烂的魔法效果。要说的是,时の魔导士在建立这个平行世界的时候,定义了一个所有可见物体的抽象类VisualObject:
1 class VisualObject { 2 public: 3 virtual void show() = 0; 4 // ... other ... 5 }
只要是出现在这个世界中,并能被世界之外的人们(比如说我们)看到的物体,都是它的子类。同时,必须实现show()方法。show定义了这个物体呈现给观众的样式。当然我们可以看到时の魔导士在创建箭矢时是如何偷懒的:
1 class Arrow : public VisualObject { 2 public: 3 virtual void show() { cout << "你想它是什么样就是什么样。" << endl; } 4 // ... other ... 5 }
当然,这是不可行的。因为肯定有人会把Arrow想像成一个巨大的炮弹,甚至一头会飞的猪,以此来增强整个故事的动画性。但无论如何,当魔导士想要告诉大家,公主射出的箭矢是附着着冰霜效果的话,他必须明确地描述这支箭矢到底长什么样。如果偷懒到底,他大可以就创造个Arrow的子类IceArrow,只需多加个关于冰晶的描述就好了。
但是问题来了,既然可以附着魔法,箭矢就可以有更多更多的效果:附着火焰的,附着闪电的,长得更好看的,等等等等……如果每一个都用子类的话,必然会导致子类数目太多。况且,我们仅仅是希望给某个对象而不是整个类添加一些特效。同时别忘了我们还要考虑箭矢之外的可以附魔的东西。怎么办才好?时の魔导士采用了Decorator模式。
请不要太在意上面这幅图到底是谁。为了能给箭矢(乃至更多物体)增加魔法效果,魔导士引入了ObjectDecorator类:
1 class ObjectDecorator : public VisualObject { 2 public: 3 ObjectDecorator(VisualObject *); 4 5 virtual void show(); 6 // ... other ... 7 private: 8 VisualObject* _component; 9 } 10 11 void ObjectDecorator::show() { 12 _component->show(); 13 }
ObjectDecorator装饰由_component实例变量引用的VisualObject,这个变量在构造器中被初始化。同时,ObjectDecorator将show的请求转发给_component。我们将看到ObjectDecorator的子类之一MagicDecorator,它将能给可视化物件添加魔法的神奇效果:
1 class MagicDecorator : public ObjectDecorator { 2 public: 3 MagicDecorator(VisualObject *, int); 4 virtual void show(); 5 // ... other ... 6 private: 7 int _magicType; 8 9 void addMagic(int); 10 } 11 12 void MagicDecorator::show() { 13 ObjectDecorator::show(); 14 addMagic(_magicType); 15 }
类似的,我们也可以实现别的装饰类。我们接下来要把这个箭矢放到这个世界中去。假设World类(一个单例类)已经为此提供了一个add2Me操作:
1 void World::add2Me(VisualObject* obj) { 2 // ... 3 obj->show(); 4 // ... 5 }
现在我们要让身处世界之外的人也看到一根箭矢,只需这么做:
1 Arrow* arrow = new Arrow(); 2 World::getInstance()->add2Me(arrow);
那么此刻,正是展现电影特效各种神奇绚丽效果的时刻了。我们在将箭矢放入世界之前,先给它加上一层寒冰魔法的装饰:
1 #define ICEMAGIC 1 2 World::getInstance()->add2Me(new MagicDecorator(arrow, ICEMAGIC));
OK,白雪公主射出了一支带有寒冰魔法的箭矢。下面的UML图说明了我们这个例子:
可以看到Decorator装饰模式有以下2个主要优点和缺点:
同样,我们在使用这个方法时,也要注意:
今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!
[学习笔记]设计模式之Decorator,布布扣,bubuko.com
原文:http://www.cnblogs.com/xieziyu/p/3592285.html