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


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

    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;
    }

  • 相关阅读:
    2017 ACM-ICPC西安网赛B-Coin
    Codeforces389D(SummerTrainingDay01-J)
    Codeforces672D(SummerTrainingDay01-I)
    VS2017.滚动条选项
    VS.自动调试
    ffmpeg.mp4.格式资料
    vs2017.unresolved external symbol __imp__fprintf&__imp____iob_func
    vs2017."const char *"的实参与"char *"的形参不兼容_goto跳过类型声明
    vue项目开发时怎么解决跨域
    vue奇怪的知识点又增加了
  • 原文地址:https://www.cnblogs.com/skyofbitbit/p/2756504.html
Copyright © 2020-2023  润新知