设计模式之实现---装饰者模式

/*****************************************************

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 何戬  hejian@cad.zju.edu.cn
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;
}

 

posted on 2012-11-06 10:36  bitbit  阅读(288)  评论(0编辑  收藏  举报