设计模式(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。


代码:

成绩单接口:ISchoolReport类
ISchoolReport.h
#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
FouthGradeSchoolReport.h
#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类
ReportDecorator.h
#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
HighScoreDecorator.h
#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类
SortDecorator.h
#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
main.cpp
#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

原创粉丝点击