设计模式(c++)笔记之八(Decorator模式)

一、描述


      装饰模式,动态地给一个对象添加一些额外的职责。就增加功能来说,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热血枫叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值