1、定义
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
2、介绍
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承。
3、源码
类关系图:
思路:1、CFouthGradeSchoolReport类为被装饰类。2、CReportDecorator理解为装饰道具的接口。3、ISchoolReport表示为装饰器。
通过ISchoolReport指针的指向,对最开始的初始创建的对象进行装饰。4、通过子类(CHighScoreDecorator、CSortDecorator)确定基类CReportDecorator指针具体指向的对象,然后对被装饰类进行具体装饰行为。
3.1、头文件
ISchoolReport.h
#pragma once
#include <iostream>
using namespace std;
class ISchoolReport
{
public:
ISchoolReport(void)
{
}
virtual ~ISchoolReport(void)
{
}
virtual void Report() = 0;
virtual void Sign(string name) = 0;
};
FouthGradeSchoolReport.h
#pragma once
#include "ischoolreport.h"
class CFouthGradeSchoolReport :
public ISchoolReport
{
public:
CFouthGradeSchoolReport(void);
~CFouthGradeSchoolReport(void);
void Report();
void Sign(string name);
};
ReportDecorator.h
#pragma once
#include "ischoolreport.h"
class CReportDecorator :
public ISchoolReport
{
public:
CReportDecorator(ISchoolReport *psr);
virtual ~CReportDecorator(void);
void Report();
void Sign(string name);
private:
ISchoolReport *m_pSchoolReport;
};
HighScoreDecorator.h
#pragma once
#include "reportdecorator.h"
#include "ISchoolReport.h"
class CHighScoreDecorator :
public CReportDecorator
{
public:
CHighScoreDecorator(ISchoolReport *psr);
~CHighScoreDecorator(void);
void Report();
private:
void ReportHighScore();
};
SortDecorator.h
#pragma once
#include "reportdecorator.h"
#include "ISchoolReport.h"
class CSortDecorator :
public CReportDecorator
{
public:
CSortDecorator(ISchoolReport *psr);
~CSortDecorator(void);
void Report();
private:
void ReportSort();
};
3.2、实现
FouthGradeSchoolReport.cpp
#include "FouthGradeSchoolReport.h"
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.cpp
#include "ReportDecorator.h"
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.cpp
#include "HighScoreDecorator.h"
#include <iostream>
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.cpp
#include "SortDecorator.h"
#include <iostream>
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();
}
Decorator.cpp
#include "ISchoolReport.h"
#include "FouthGradeSchoolReport.h"
#include "HighScoreDecorator.h"
#include "SortDecorator.h"
void DoIt()
{
ISchoolReport *psr = new CFouthGradeSchoolReport();
psr->Report();//看成绩单
psr->Sign("老三");//很开心,就签字了
delete psr;
}
void DoNew()
{
cout << "----------分部分进行装饰----------" << endl;
ISchoolReport *psr = new CFouthGradeSchoolReport();//原装成绩单,psr指向CFouthGradeSchoolReport
ISchoolReport *pssr = new CSortDecorator(psr);//又加了成绩排名的说明,pssr指向CSortDecorator,修改类父类CReportDecorator的指向
ISchoolReport *phsr = new CHighScoreDecorator(pssr);//加了最高分说明的成绩单,phsr指向CHighScoreDecorator,修改父类CReportDecorator的指向
phsr->Report();//看成绩单,phsr指向CHighScoreDecorator
//phsr指向CHighScoreDecorator
phsr->Sign("老三");//很开心,就签字了
//先装饰哪个不重要,顺序已经在装饰内部确定好,但一定要调用最后一个装饰器的接口。
//ISchoolReport *phsr = new CHighScoreDecorator(psr);//加了最高分说明的成绩单 phsr指向CHighScoreDecorator
//ISchoolReport *pssr = new CSortDecorator(phsr);//又加了成绩排名的说明pssr指向CSortDecorator
//pssr->Report();//看成绩单
//pssr->Sign("老三");//很开心,就签字了
delete pssr;
delete phsr;
delete psr;
}
int main()
{
//在装饰之前,可以用继承的办法,来进行简单的修饰
DoIt();
//但如果需要修饰的项目太多呢?或者装饰的项目不是固定的,继承显然会变得更复杂
DoNew();
system("pause");
return 0;
}
4、结果
参考文献:《菜鸟教程》 https://blog.csdn.net/phiall/article/details/52199659博客