/*****************************************************
component.h
****************************************************/
#pragma once
#include <iostream>
#include <string>
using namespace std;
/////////////////////////////
//组件类的基类
//1. 所有组件全都派生自这个组件
//2. 装饰都类的纯虚基类也派生自这个组件
class CBaverage
{
protected:
string m_description;
float m_price;
public:
virtual float cost() = 0;
string& getDescription(){
return m_description;
}
CBaverage() : m_price(0.0f){}
};
//黑咖啡类,什么都不加
class CBlackCoffee : public CBaverage
{
public:
CBlackCoffee(){
m_description = "Black Coffee";
m_price = 0.1f;
}
float cost(){
return m_price;
}
};
//摩卡咖啡
class CMocaCoffee : public CBaverage
{
public:
CMocaCoffee(){
m_description = "Moca Coffee";
m_price = 0.17f;;
}
float cost(){
return m_price;
}
};
/*****************************************************************
decorator.h
****************************************************************/
#pragma once;
#include <iostream>
using namespace std;
#include "component.h"
/////////////////////////////////////////
//装饰者基类,用来装饰一个
/*装饰者基类也必须从Baverage的纯虚基类中派生出来
但是这个派生并不是因为要用到Baverage基类的方法,
而是为了做类型匹配用的。这样做就可以使得一个Baverage的基类指针指向一个装饰者类的实体
*/
////////////////////////////////////////
class CDecorator : public CBaverage
{
protected:
//保留一个成员变量,来保存被装饰组件的指针(这里也可以是引用)
//但,如果一直要保存对象的话,那么对内存是一个考验,所以我在这里暂时先把原对象的状态和属性先保存起来。
//CBaverage* m_bev;
public:
//CDecorator():m_bev(NULL){};
//使这个装饰者基类为纯虚函数
virtual string& getDescription() = 0;
};
////////////////////////////////////////////////
//给任一Baverage加上Tea的装饰者类
class CCoffeeWithTea : public CDecorator
{
public:
//用Tea来装饰一个以CBaverage为基类的对象
CCoffeeWithTea(CBaverage* dBev){
//m_bev = dBev;
//这就是装饰者的作用
m_description = dBev->getDescription() + " with tea";
m_price = 0.12f + dBev->cost();
}
float cost(){
return m_price;
}
string& getDescription(){
return m_description;
}
};
////////////////////////////////////////////////
//给任一Baverage加上Sugar的装饰者类
class CCoffeeWithSugar : public CDecorator
{
public:
//用Sugar来装饰一个以CBaverage为基类的对象
CCoffeeWithSugar(CBaverage* dBev){
//m_bev = dBev;
//这就是装饰者的作用
m_price = 0.08f + dBev->cost();
m_description = dBev->getDescription() + " with Sugar";
}
float cost(){
return m_price;
}
string& getDescription(){
return m_description;
}
};
/*****************************************************************
testDecorator.cpp
*****************************************************************/
/*
设计模式: 装饰者模式
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹的替代方案。
类:
1. 有一个所有组件的虚基类。
2. 所有组件都从这个虚基类中派生下来。 is-a 虚组件
3. 装饰者基类也从这个组件中继承,并重载某些必须被害人装饰者重写的方法,且将基变为纯虚函数。 is-a 虚组组
4. 每个组件都可以单独使用,或者被装饰者包起来使用。
5. 每一个装饰者都“有一个has a”组件,也就是说,装饰者有一个实例变量以保存某个component的指针或引用。
6. 装饰者实类有一个实例变量,可以记录所装饰的事物
7. 装饰者可以加上新的方法,新行为是通过在旧行为前面或后面做一些计算来添加的。
注意:非常重要的是,装饰者也必须继承于组件的基类,这么做的重点并不是利用继承获得“行为”,而是尽可能的保持装饰者和被装饰者必须是一样的类型,也就是有共同的超类。
装饰者模式会导致出现许多小对象,如果过度使用,会让程序变得很复杂。而且管理其资源泄漏也是一个严峻的考验。
@@@@@@@@@@@@@@@@@@@@@@@@@@@
这个程序做的事:
不停的为某种咖啡添加调味品。
比如说:为任一咖啡添加糖,那么这个添加过程就是 "装饰者"类 CCoffeeWithSugar所做的。
装饰者类的构造函数的一个参数是要被装饰的对象。
@@@@@@@@@@@@@@@@@@@@@@@@@@@
by 何戬 [email protected]
2009. 6. 1
*/
#include <iostream>
using namespace std;
#include "decorator.h"
int main()
{
CBaverage* temp = NULL;
//先来一杯moca
CBaverage* moca = new CMocaCoffee();
cout<<moca->getDescription()<<" will costs: "<<moca->cost()<<endl;
//moca太苦了, 给我加点糖
temp = moca;
moca = new CCoffeeWithSugar(moca);
cout<<moca->getDescription()<<" will costs: "<<moca->cost()<<endl;
//注意,C++没有垃圾回收入机制,所以这里要delete原先的moca
if(temp){
delete temp;
temp = NULL;
}
//还是太苦, 再给我加点糖
temp = moca;
moca = new CCoffeeWithSugar(moca);
cout<<moca->getDescription()<<" will costs: "<<moca->cost()<<endl;
//注意,C++没有垃圾回收入机制,所以这里要delete原先的moca
if(temp){
delete temp;
temp = NULL;
}
return 0;
}