Structural.Decorator(结构型模式—装饰模式)

装饰模式的结构和说明

①Component:组件对象的接口,可以给这些对象动态地添加职责。

  ②ConcreteComponent:具体的组件对象,实现组件对象接口,通常就是被装饰器装饰的原始对象,也就是可以给这个对象添加职责。

  ③Decorator:所有装饰器的抽象父类,需要定义一个与组件接口一致的接口,并持有一个Component对象的指针,其实就是持有一个被装饰的对象。之所以从Decorator继承而来,除了与被装饰对象接口相同,还是有个原因是Decorator本身也可以被进一步的装饰,形成多层的装饰。注意,装饰后仍然是一个Component对象,而且其功能更为复杂。

  ④ConcreteDecorator:实际的装饰器对象,实现具体要向被装饰对象添加的功能。

思考装饰模式

  ①装饰模式的本质动态组。动态是手段,组合才是目的。通过对象组合(而不是继承)来实现为被装饰对象透明的增加功能,而且也可以控制功能的访问。

  ②装饰模式的动机:由于继承为类型引入的静态特质,使得通过继承扩展方式缺乏灵活性,并且随着子类的增多,会导致子类的膨胀。而装饰模式可以根据需要来动态地使“对象功能扩展”,避免子类膨胀问题

  ③装饰器:不仅仅可以给被装饰对象增加功能,还可以根据需要选择是否调用被装饰对象的功能。如果不调用,那就变成完全重新实现,相当于动态修改了被装饰对象的功能。同时装饰器一定要实现和组件类一致的接口,保证它们是同一个类型,并具有同一个外观,这样组合完成的装饰才能够递归调用下去

【编程实验】奖金的计算

//声明文件

//结构型模式:装饰模式
//场景:计算奖金的方法。
//奖金的计算方式:
//1.奖金分为个人奖金和业务主管(经理)两种不同的计算方式等。
//2.个人奖金大致有个人当月业务奖金、个人累计奖金、个人业务增长奖金、及时回款奖金
//  限时成交加码奖等。对于业务主管除了个人奖金外,还有团队累计奖金和团队业务增长
//  奖金、团队盈利奖等。

//简化后的奖金计算体系
//1.每个人当月业务奖金 = 当月销售额* 3%
//2.每个人累计奖金 = 总的回款额* 0.1%
//3.团队奖金 = 团队总销售额* 1%
#include <iostream>
#include <map>
#include <string>

using namespace std;

//********************辅助类*********************************
//在内存中模拟数据库,准备测试数据,好计算奖金
class CTmpDB{
private:
	CTmpDB(){}
public: //记录每个人的月度销售额,只用了人员,月份没有用
	static map<string, double> mpSalary;
};

//************************抽象组件类******************
//计算奖金的组件接口
class CMoney{
public:
	virtual ~CMoney();
	virtual double MakeLiving(string user) = 0;
};

//基本的实现计算奖金的类,也是被装饰器装饰的对象
class CBasePay : public CMoney{
public:
	~CBasePay();
	double MakeLiving(string user);
};
//************************定义抽象的装饰器**********************
class CMoneyDecorator : public CMoney{
protected:
	CMoney* pBase;
public:
	CMoneyDecorator(CMoney* base);
	~CMoneyDecorator();
	double MakeLiving(string user);
};

//定义一系列的装饰器对象
//装饰器对象:计算当月业务奖金
class CMonthPrize : public CMoneyDecorator{
public:
	CMonthPrize(CMoney* base);
	~CMonthPrize();
	double MakeLiving(string user);
};
//装饰器对象:计算累计奖金
class CSumPrize : public CMoneyDecorator{
public:
	CSumPrize(CMoney* base);
	~CSumPrize();
	double MakeLiving(string user);
};

//装饰器对象:计算当月团队业务奖金
class CGroupPrize : public CMoneyDecorator{
public:
	CGroupPrize(CMoney* base);
	~CGroupPrize();
	double MakeLiving(string user);
};

//实现文件

//********************辅助类*********************************
//在内存中模拟数据库,准备测试数据,好计算奖金
static map<string, double>::value_type init_value[]=
{
	map<string, double>::value_type("ZhangSan", 10000.0),
	map<string, double>::value_type("LiSi",     20000.0),
	map<string, double>::value_type("WangWu",   30000.0)
};
map<string, double> CTmpDB::mpSalary(init_value, init_value+3);

//************************抽象组件类******************
//计算奖金的组件接口
CMoney::~CMoney(){}
//基本的实现计算奖金的类,也是被装饰器装饰的对象
CBasePay::~CBasePay(){ cout << "~基本工资" << endl;}
double CBasePay::MakeLiving(string user)
{
	cout << "基本工资:" << CTmpDB::mpSalary[user] << endl << "*************" << endl;
	return CTmpDB::mpSalary[user];
}
//************************定义抽象的装饰器**********************
CMoneyDecorator::CMoneyDecorator(CMoney* base) : pBase(base){}
double CMoneyDecorator::MakeLiving(string user){ return pBase->MakeLiving(user);}
CMoneyDecorator::~CMoneyDecorator(){delete pBase;}

//定义一系列的装饰器对象
//装饰器对象:计算当月业务奖金
CMonthPrize::CMonthPrize(CMoney* base) : CMoneyDecorator(base){}
CMonthPrize::~CMonthPrize(){cout << "~当月业务奖金" << endl;}
double CMonthPrize::MakeLiving(string user)
{
	double dMoney = pBase->MakeLiving(user)*0.03;
	cout << "当月业务奖金:" << dMoney << endl;
	return pBase->MakeLiving(user) + dMoney;
}
//装饰器对象:计算累计奖金
CSumPrize::CSumPrize(CMoney* base) : CMoneyDecorator(base){}
CSumPrize::~CSumPrize(){cout << "~累计奖金" << endl;}
double CSumPrize::MakeLiving(string user)
{
	cout << "累计奖金:" << 10000*0.02 << endl;
	return pBase->MakeLiving(user) + 10000*0.02;
}


//装饰器对象:计算当月团队业务奖金
CGroupPrize::CGroupPrize(CMoney* base) : CMoneyDecorator(base){}
CGroupPrize::~CGroupPrize(){cout << "~团队业务奖金" << endl;}
double CGroupPrize::MakeLiving(string user)
{
	double dMoney = 0.0;
	for(map<string, double>::iterator it = CTmpDB::mpSalary.begin(); it != CTmpDB::mpSalary.end(); it++){
		dMoney += it->second;
	}
	cout << "团队业务奖金:" << dMoney*0.01 << endl;
	return pBase->MakeLiving(user) + dMoney*0.01;
}

//测试客户端

void main()
{
	CMoney* pBase = new CBasePay();
	CMoney* pMonthPrize = new CMonthPrize(pBase);
	CMoney* pSumPrize = new CSumPrize(pMonthPrize);
	CGroupPrize* pGroupPrize = new CGroupPrize(pSumPrize);

	cout << "ZhangSan : " << pGroupPrize->MakeLiving("ZhangSan") << endl;

	delete pGroupPrize;
}


猜你喜欢

转载自blog.csdn.net/KnightOnHourse/article/details/79987762