设计模式(c++)笔记之八(Decorator模式)
来源:互联网 发布:linux下的arm模拟器 编辑:程序博客网 时间:2024/06/06 05:52
一、描述
装饰模式,动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
问题:
在 OO 设计和开发过程,可能会经常遇到以下的情况:我们需要为一个已经定义好的类添加新的职责(操作),通常的情况我们会给定义一个新类继承自定义好的类,这样会带来一个问题(将在本模式的讨论中给出)。通过继承的方式解决这样的情况还带来了系统的复杂性,因为继承的深度会变得很深。
而 Decorator 提供了一种给类增加职责的方法,不是通过继承实现的,而是通过组合。有关这些内容在讨论中进一步阐述。
模式选择:
Decorator 模式典型的结构图为:
图 2-1:Decorator Pattern 结构图在结构图
ConcreteComponent 和 Decorator 需要有同样的接口,因此ConcreteComponent 和 Decorator 有着一个共同的父类。这里有人会问,让 Decorator 直接维护一个指向 ConcreteComponent 引用(指针)不就可以达到同样的效果,答案是肯定并且是否定的。肯定的是你可以通过这种方式实现,否定的是你不要用这种方式实现,因为通过这种方式你就只能为这个特定的 ConcreteComponent 提供修饰操作了,当有了一个新的 ConcreteComponent 你又要去新建一个 Decorator 来实现。
但是通过结构图中的ConcreteComponent 和 Decorator 有一个公共基类,就可以利用 OO 中多态的思想来实现只要是 Component 型别的对象都可以提供修饰操作的类,这种情况下你就算新建了 100 个Component 型别的类 ConcreteComponent,也都可以由 Decorator 一个类搞定。
这也正是Decorator 模式的关键和威力所在了。
当然如果你只用给 Component 型别类添加一种修饰,则 Decorator 这个基类就不是很必要了。
二、实例
就说说"我"上小学的的糗事吧。我上小学的时候学习成绩非常的差,班级上 40 多个同学,我基本上都是在排名 45 名以后,按照老师给我的定义就是“不是读书的料”,但是我老爸管的很严格,明知道我不是这块料,还是往赶鸭子上架,每次考试完毕我都是战战兢兢的,“竹笋炒肉”是肯定少不了的,能少点就少点吧,肉可是自己的呀。四年级期末考试考完,学校出来个很损的招儿(这招儿现在很流行的),打印出成绩单,要家长签字,然后才能上五年级,我那个恐惧呀,不过也就是几秒钟的时间,玩起来什么都忘记了。当时,我的成绩(语文 62 数学65 体育 98 自然 63),
你要知道在小学低于 90 分基本上就是中下等了,唉,爱学习的人太多了!怎么着,那我把这个成绩单给老爸看看?
就这成绩还要我签字?!老爸就开始找笤帚,我的屁股已经做好了准备,肌肉要绷紧,要不那个太疼了!哈哈,幸运的是,这个不是当时的真实情况,我没有直接把成绩单交给老爸,而是在交给他之前做了点技术工作,我要把成绩单封装一下,封装分类两步走:
第一步:跟老爸说各个科目的最高分,语文最高是 75,数学是 78,自然是 80,然老爸觉的我成绩与最高分数相差不多,这个是实情,但是不知道是什么原因,反正期末考试都考的不怎么样,但是基本上都集中在 70 分以上,我这 60 多分基本上还是垫底的角色;
第二步:在老爸看成绩单后,告诉他我是排名第 38 名,全班,这个也是实情,为啥呢?有将近十个同学退学了!这个情况我是不说的。不知道是不是当时第一次发成绩单,学校没有考虑清楚,没有写上总共有多少同学,排名第几名等等,反正是被我钻了个空子。类图如下:
ISchoolReport,成绩单接口
CFourthGradeSchoolReport,四年级成绩单
ReportDecorator,成绩单装饰器基类
HighScoreDecorator,最高分装饰器
SortDecorator,班级排名装饰器
说明:对“四年级成绩单”进行装饰,ReportDecorator必然有一个private变量指向ISchoolReport。
#ifndef Decorator_ISchoolReport_h#define Decorator_ISchoolReport_h#include<iostream>using std::string;class ISchoolReport{public: ISchoolReport(void){} virtual ~ISchoolReport(void){} virtual void Report() = 0; virtual void Sign(string name) = 0;};#endif
四年级成绩单:FouthGradeSchoolReport
#ifndef __Decorator__FouthGradeSchoolReport__#define __Decorator__FouthGradeSchoolReport__#include <iostream>#include "ISchoolReport.h"class CFouthGradeSchoolReport:public ISchoolReport{public: CFouthGradeSchoolReport(void); ~CFouthGradeSchoolReport(void); void Report(); void Sign(string name);};#endif /* defined(__Decorator__FouthGradeSchoolReport__) */FouthGradeSchoolReport.cpp
#include "FouthGradeSchoolReport.h"using std::cout;using std::endl;using std::string;CFouthGradeSchoolReport::CFouthGradeSchoolReport(void){ }CFouthGradeSchoolReport::~CFouthGradeSchoolReport(void){ }void CFouthGradeSchoolReport::Report(){ cout << "尊敬的XXX家长:" << endl; cout << "......" << endl; cout << "语文62 数学65 体育98 自然63" << endl; cout << "......" << endl; cout << " 家长签名:" << endl;}void CFouthGradeSchoolReport::Sign(string name){ cout << "家长签名为:" << name.c_str() << endl;}
成绩单装饰器基类:ReportDecorator类
#ifndef __Decorator__ReportDecorator__#define __Decorator__ReportDecorator__#include <iostream>#include "ISchoolReport.h"class CReportDecorator:public ISchoolReport{public: CReportDecorator(ISchoolReport *psr); virtual ~CReportDecorator(void); void Report(); void Sign(string name);private: ISchoolReport *m_pSchoolReport;};#endif /* defined(__Decorator__ReportDecorator__) */ReportDecorator.cpp
#include "ReportDecorator.h"using std::string;CReportDecorator::CReportDecorator(ISchoolReport *psr){ this->m_pSchoolReport = psr;}CReportDecorator::~CReportDecorator(void){ }void CReportDecorator::Report(){ this->m_pSchoolReport->Report();}void CReportDecorator::Sign(string name){ this->m_pSchoolReport->Sign(name);}
最高分装饰器:HighScoreDecorator
#ifndef __Decorator__HighScoreDecorator__#define __Decorator__HighScoreDecorator__#include <iostream>#include "ReportDecorator.h"#include "ISchoolReport.h"class CHighScoreDecorator:public CReportDecorator{public: CHighScoreDecorator(ISchoolReport *psr); ~CHighScoreDecorator(void); void Report();private: void ReportHighScore();};#endif /* defined(__Decorator__HighScoreDecorator__) */HighScoreDecorator.cpp
#include "HighScoreDecorator.h"using std::cout;using std::endl;CHighScoreDecorator::CHighScoreDecorator(ISchoolReport *psr):CReportDecorator(psr){}CHighScoreDecorator::~CHighScoreDecorator(void){}void CHighScoreDecorator::Report(){ this->ReportHighScore(); this->CReportDecorator::Report();}void CHighScoreDecorator::ReportHighScore(){ cout << "这次考试语文最高是75, 数学是78, 自然是80" << endl;}
班级排名装饰器:SortDecorator类
#ifndef __Decorator__SortDecorator__#define __Decorator__SortDecorator__#include <iostream>#include "ReportDecorator.h"#include "ISchoolReport.h"class CSortDecorator:public CReportDecorator {public: CSortDecorator(ISchoolReport *psr); ~CSortDecorator(void); void Report();private: void ReportSort(); };#endif /* defined(__Decorator__SortDecorator__) */SortDecorator.cpp
#include "SortDecorator.h"using std::cout;using std::endl;CSortDecorator::CSortDecorator( ISchoolReport *psr ) : CReportDecorator(psr){}CSortDecorator::~CSortDecorator(void){}void CSortDecorator::ReportSort(){ cout << "我是排名第38名..." << endl;}void CSortDecorator::Report(){ this->CReportDecorator::Report(); this->ReportSort();}
主程序:main
#include <stdio.h>#include "ISchoolReport.h"#include "FouthGradeSchoolReport.h"#include "FouthGradeSchoolReport.h"#include "HighScoreDecorator.h"#include "SortDecorator.h"#include <iostream>using std::cout;using std::endl;void DoIt(){ ISchoolReport *psr = new CFouthGradeSchoolReport(); psr->Report();// psr->Sign("老三");//很开心,就签字了 delete psr;}void DoNew(){ cout << "----------分部分进行装饰----------" << endl; ISchoolReport *psr = new CFouthGradeSchoolReport();//原装成绩单 ISchoolReport *pssr = new CSortDecorator(psr);//又加了成绩排名的说明 ISchoolReport *phsr = new CHighScoreDecorator(pssr);//加了最高分说明的成绩单 phsr->Report();//看成绩单 phsr->Sign("老三");//很开心,就签字了 //先装饰哪个不重要,顺序已经在装饰内部确定好,但一定要调用最后一个装饰器的接口。 //ISchoolReport *phsr = new CHighScoreDecorator(psr);//加了最高分说明的成绩单 //ISchoolReport *pssr = new CSortDecorator(phsr);//又加了成绩排名的说明 //pssr->Report();//看成绩单 //pssr->Sign("老三");//很开心,就签字了 delete pssr; delete phsr; delete psr; }int main(int argc, const char * argv[]){ //在装饰之前,可以用继承的办法,来进行简单的修饰 DoIt(); //但如果需要修饰的项目太多呢?或者装饰的项目不是固定的,继承显然会变得更复杂 DoNew(); // insert code here... printf("Hello, World!\n"); return 0;}
结果如下:
参考文献:《设计模式之禅》,《GoF_23种设计模式解析》
参考博客:http://www.cnblogs.com/wanggary/archive/2011/04/18/2020254.htm
- 设计模式(c++)笔记之八(Decorator模式)
- 设计模式之八 --- 装饰模式(Decorator)
- 设计模式之八 --- 装饰模式(Decorator)
- 设计模式之八------Decorator(装饰)
- 设计模式笔记之装饰者模式(Decorator Pattern)
- 设计模式实例(Lua)笔记之七(Decorator模式)
- 浅谈设计模式之八——Decorator模式
- 23种设计模式之八(结构型模式)Decorator模式
- 【设计模式】之装饰模式(Decorator)
- 设计模式之装饰模式(Decorator)
- 设计模式之 装饰模式(Decorator)
- 设计模式之装饰模式(Decorator)
- 设计模式之装饰(Decorator)模式
- 设计模式之装饰模式(Decorator)
- 设计模式之装饰模式(Decorator)
- 设计模式笔记之Decorator Pattern
- 设计模式笔记-Decorator模式
- 设计模式之Decorator
- redhat6.2启动模式更改
- STM8 FOR IAR 中实现绝对地址跳转
- Linux磁盘管理:LVM逻辑卷的拉伸及缩减
- 新的json在后台使用的方法
- XILINX DCM and ALTERA PLL(2)
- 设计模式(c++)笔记之八(Decorator模式)
- SSL协议的握手过程
- 戴尔推出Venue 7和Venue 8两款入门级Android平板电脑
- extField限制只能输入一定长度的字符
- Step By Step(Lua调用C函数)
- WebService的简单使用
- XILINX DCM and ALTERA PLL(1)
- 一个字符串 是否包含另外一个字符串
- 约瑟夫环(数组模拟实现)