大话设计模式之(装饰器模式)
来源:互联网 发布:ubuntu 14.04 反应慢 编辑:程序博客网 时间:2024/06/06 13:02
导言:我曾经以为我可以用继承处理一切。后来我领教到运行时扩展,远比编译时期的继承威力大。装饰器模式可以给爱用继承的人一个全新的眼界。一旦你熟悉了装饰器模式,你将学会如何在运行的过程中给对象赋予新的指责和功能。
先不谈模式,如果现在要你开发一个可以给人搭配不同服饰的系统,不如类似QQ、网络游戏或论坛都有的Avatar系统,你怎么开发?
半小时后,小菜的第一版代码出炉。
代码结构图:
#include "stdafx.h"#include <iostream>using namespace std;class Person{public: Person(string n){ name = n; } void wearTShirts(){ cout << "大T恤 "; } void wearBigTrouser(){ cout << "垮裤 "; } void wearSneakers(){ cout << "破球鞋 "; } void wearSuit(){ cout << "西装 "; } void wearTie(){ cout << "领带 "; } void wearLeatherShoes(){ cout << "皮鞋 "; } void show(){ cout << "装扮的" << name.c_str(); }private: string name;};int _tmain(int argc, _TCHAR* argv[]){ Person* p = new Person("小菜"); cout << "第一种装扮:" << endl; p->wearTShirts(); p->wearBigTrouser(); p->wearSneakers(); p->show(); cout << "第二种装扮:" << endl; p->wearSuit(); p->wearTie(); p->wearLeatherShoes(); p->show(); return 0;}
功能是实现了,现在的问题是如果我要增加 “超人” 的装扮,你得如何做?“那就改改 ‘Person’ 类就行了”,小菜说完就反应过来了,“哦,不对,这就违背开放-封闭原则了。”
下面我们来说说装饰模式。装饰模式可以动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类要更为灵活。
“啊,装饰这个词真好,无论衣服、鞋子、领带、披风其实都可以理解为对人的装饰,我们来看一下他的结构。”
结构图
Component是定义了一个对象接口,可以给这些对象动态的添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说就无需知道Decorator的存在。至于ConcreteDecorator就是个具体的装饰对象,起到给Component添加职责的功能。
下面来看看具体的代码实现
Component类
class Component{public: virtual void operate() = 0;};
ConcreteComponent类
class ConcreteComponent : public Component{public: virtual void operate() override { cout << "具体对象的操作" << endl; }};
Decorate类
class Decorate : public Component{public: Decorate(Component* c){ comp = c; } virtual void operate() override { comp->operate(); }private: Component* comp = nullptr;};
ConcreteDecorate类
class ConcreteDecorateA : public Decorate{public: ConcreteDecorateA (Component* c) : Decorate(c) { comp = c; } virtual void operate() override { Decorate::operate(); addedState = "New state"; cout << "具体装饰对象A的操作" << endl; }private: string addedState;};class ConcreteDecorateB : public Decorate{public: ConcreteDecorateB(Component* c) : Decorate(c) { comp = c; } virtual void operate() override { Decorate::operate(); addedBehavior(); cout << "具体装饰对象B的操作" << endl; }private: void addedBehavior() { cout << "addedBehavior" << endl; }};
客户端代码
int _tmain(int argc, _TCHAR* argv[]){ ConcreteComponent* c = new ConcreteComponent(); ConcreteDecorateA* d1 = new ConcreteDecorateA(c); ConcreteDecorateA* d2 = new ConcreteDecorateA(d1); d2->operate(); return 0;}
“我明白了,原来装饰模式是利用类的构造来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。用刚才的例子来说,就是我们完全可以先穿外裤,再穿内裤,而不一定要先内后外。”
“既然你明白了,还不赶快把刚才的例子改成装饰模式的代码?”
“我还有个问题,刚才我写的例子中的 ‘人’ 类是Component还是ConcreteComponent呢?”
“哈,学习模式要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样道理,如果只有一个ConcreteDecorator类,那么没必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。”
“啊,原来如此。在这里我们就没有必要有Component类了,直接让服饰类Decorator继承人类ConcreteComponent就可以了。”
二十分钟后,小菜的第三版代码出炉。
代码结构图:
Person类
class Person{public: Person(string n){ name = n; } virtual void show(){ cout << "装扮的" << name.c_str(); }private: string name;};
Finery(服饰类)
class Finery : public Person{public: void decorate(Person* p){ component = p; } virtual void show() { if (component) { component->show(); } }private: Person* component;};
具体服饰类
class TShirts : public Finery{public: virtual void show() { cout << "大T恤 "; Finery::show(); }};class BigTrouser : public Finery{public: virtual void show() { cout << "垮裤 "; Finery::show(); }};//其余类似,省略
客户端代码
int _tmain(int argc, _TCHAR* argv[]){ Person* p = new Person("小菜"); TShirts* ts = new TShirts(); Suit* st = new Suit(); BigTrouser* bt = new BigTrouser(); //用大T恤装饰了一个光着的小菜 ts->decorate(p); //用垮裤装饰了一个穿着大T恤的小菜 bt->decorate(ts); //用西装装饰了一个穿着垮裤, 大T恤的小菜 st->decorate(bt); bt->show(); return 0;}
总结:
装饰模式是为已有功能动态的添加更多功能的一种方式。
当系统需要新的功能时,我们原有的做法是向旧的代码加入新的代码。这些新的代码通常装饰了原有类的核心职责和主要行为,不如用西装来装饰小菜,但这种做法的主要问题在于,在主类中加入了新的字段,新的方法,新的逻辑,从而增加了主类的复杂度,同时也违背了开闭原则。
装饰模式提供了一个很好的解决方案,它把每个要装饰新增的功能放在单独的类中,并让这个类装饰他要包装的类。因此在需要执行特殊行为时,客户代码就可以运行时根据需要有选择,有顺寻的使用装饰功能装饰对象了。这样就把类的核心功能和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑。
- 大话设计模式之装饰器模式
- 大话设计模式之(装饰器模式)
- 大话设计之装饰模式
- 大话设计模式之装饰设计模式
- 大话设计模式之-----装饰模式
- 大话设计模式之装饰模式
- 大话设计模式之装饰模式
- 大话设计模式之装饰模式
- 大话设计模式之装饰模式
- 大话设计模式之装饰者模式
- 三、大话设计模式 之 装饰模式
- 大话设计模式之装饰者模式
- 大话设计模式读后感之装饰模式
- 大话设计模式之装饰模式
- 大话设计模式之装饰模式
- 《大话设计模式》之装饰模式
- 《大话设计模式》java实现之装饰器模式
- 大话设计模式之装饰模式(小菜扮靓)
- [UVa 712] S 树(S-Trees)
- os.walk()
- QNX学习笔记之QNX Momentics IDE使用笔记
- 视频分辨率
- 2017年的电子设计竞赛快开始了,学放大器的小伙伴们进来一起谈论一下!
- 大话设计模式之(装饰器模式)
- logback高级特性,异步记录日志
- The action could not be completed.Try again.
- live555接实时视频流+ffmpeg解+x264再编
- 关于jar包和工程src里面class相同的加载优先级问题
- MFC文件对话框不能选太多文件的解决方法
- 网站服务器、网站被攻击怎么办
- 大数相乘
- hdoj 6034(2017 Multi-University Training Contest