• c++设计模式:装饰者模式(Decorator Pattern)


    定义:

    装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    场景:

    我们购买咖啡的时候,可以要求在其中加入各种调料,例如:蒸奶、豆浆、摩卡或覆盖奶泡,而咖啡店也会根据所加入的调料收取不同的费用,所以当我们设计订单系统的时候就需要考虑到这些调料部分啦。顾客的需求不一,如果我们针对每种配方都声明一个类得话,系统的维护将会十分头疼。此时装饰者模式就派上用场啦。我们可以根据顾客的需要动态的扩展顾客定制的咖啡,让其加上不同的调料,最终计算出顾客所需缴纳的费用。它的实现有点类似于递归,在实际使用的时候可以慢慢体会。

    类图:

    c++代码如下:

    不使用指针版本:

    #include <iostream>
    #include <string>
    using namespace std;

    class Beverage
    {
    public:
    virtual ~Beverage() {};
    virtual string getDescription(); // 必须是虚函数,否则会造成后期使用时描述显示不正确
    virtual double cost() = 0;
    protected:
    string m_description;
    };

    class CondimentDecorator:public Beverage
    {
    public:
    virtual string getDescription() = 0;
    };

    class Espresso:public Beverage
    {
    public:
    Espresso();
    double cost();
    };

    class HouseBlend:public Beverage
    {
    public:
    HouseBlend();
    double cost();
    };

    class DarkRoast:public Beverage
    {
    public:
    DarkRoast();
    double cost();
    };

    class Decaf:public Beverage
    {
    public:
    Decaf();
    double cost();
    };

    class Mocha:public CondimentDecorator
    {
    public:
    Mocha(Beverage* pBeverage);
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    class Milk:public CondimentDecorator
    {
    public:
    Milk(Beverage* pBeverage);
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    class Soy:public CondimentDecorator
    {
    public:
    Soy(Beverage* pBeverage);
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    class Whip:public CondimentDecorator
    {
    public:
    Whip(Beverage* pBeverage);
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    string Beverage::getDescription()
    {
    return m_description;
    }

    Espresso::Espresso()
    {
    m_description = "Espresso";
    }

    double Espresso::cost()
    {
    return 1.99;
    }

    HouseBlend::HouseBlend()
    {
    m_description = "House Blend Coffee";
    }

    double HouseBlend::cost()
    {
    return 0.89;
    }

    DarkRoast::DarkRoast()
    {
    m_description = "Dark Roast Coffee";
    }

    double DarkRoast::cost()
    {
    return 0.99;
    }

    Decaf::Decaf()
    {
    m_description = "Decaf Coffee";
    }

    double Decaf::cost()
    {
    return 1.05;
    }

    Mocha::Mocha(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    string Mocha::getDescription()
    {
    return m_pBeverage->getDescription() + " + Mocha";
    }

    double Mocha::cost()
    {
    return 0.20 + m_pBeverage->cost();
    }

    Milk::Milk(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    string Milk::getDescription()
    {
    return m_pBeverage->getDescription() + " + Milk";
    }

    double Milk::cost()
    {
    return 0.10 + m_pBeverage->cost();
    }

    Soy::Soy(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    string Soy::getDescription()
    {
    return m_pBeverage->getDescription() + " + Soy";
    }

    double Soy::cost()
    {
    return 0.15 + m_pBeverage->cost();
    }

    Whip::Whip(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    string Whip::getDescription()
    {
    return m_pBeverage->getDescription() + " + Whip";
    }

    double Whip::cost()
    {
    return 0.10 + m_pBeverage->cost();
    }

    int main()
    {
    Espresso espresso;
    cout << espresso.getDescription() << " $" << espresso.cost() << endl;

    DarkRoast darkRoast;
    Mocha mocha1(&darkRoast);
    Mocha mocha2(&mocha1);
    Whip whip1(&mocha2);
    cout << whip1.getDescription() << " $" << whip1.cost() << endl;

    HouseBlend houseBlend;
    Soy soy1(&houseBlend);
    Mocha mocha3(&soy1);
    Whip whip2(&mocha3);
    cout << whip2.getDescription() << " $" << whip2.cost() << endl;

    return 0;
    }

    使用指针版本:

    #include <iostream>
    #include <string>
    using namespace std;

    class Beverage
    {
    public:
    virtual ~Beverage() {};
    virtual string getDescription();
    virtual double cost() = 0;
    protected:
    string m_description;
    };

    class CondimentDecorator:public Beverage
    {
    public:
    virtual string getDescription() = 0;
    };

    class Espresso:public Beverage
    {
    public:
    Espresso();
    double cost();
    };

    class HouseBlend:public Beverage
    {
    public:
    HouseBlend();
    double cost();
    };

    class DarkRoast:public Beverage
    {
    public:
    DarkRoast();
    double cost();
    };

    class Decaf:public Beverage
    {
    public:
    Decaf();
    double cost();
    };

    class Mocha:public CondimentDecorator
    {
    public:
    Mocha(Beverage* pBeverage);
    ~Mocha();
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    class Milk:public CondimentDecorator
    {
    public:
    Milk(Beverage* pBeverage);
    ~Milk();
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    class Soy:public CondimentDecorator
    {
    public:
    Soy(Beverage* pBeverage);
    ~Soy();
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    class Whip:public CondimentDecorator
    {
    public:
    Whip(Beverage* pBeverage);
    ~Whip();
    string getDescription();
    double cost();
    protected:
    Beverage* m_pBeverage;
    };

    string Beverage::getDescription()
    {
    return m_description;
    }

    Espresso::Espresso()
    {
    m_description = "Espresso";
    }

    double Espresso::cost()
    {
    return 1.99;
    }

    HouseBlend::HouseBlend()
    {
    m_description = "House Blend Coffee";
    }

    double HouseBlend::cost()
    {
    return 0.89;
    }

    DarkRoast::DarkRoast()
    {
    m_description = "Dark Roast Coffee";
    }

    double DarkRoast::cost()
    {
    return 0.99;
    }

    Decaf::Decaf()
    {
    m_description = "Decaf Coffee";
    }

    double Decaf::cost()
    {
    return 1.05;
    }

    Mocha::Mocha(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    Mocha::~Mocha()
    {
    delete m_pBeverage;
    }

    string Mocha::getDescription()
    {
    return m_pBeverage->getDescription() + " + Mocha";
    }

    double Mocha::cost()
    {
    return 0.20 + m_pBeverage->cost();
    }

    Milk::Milk(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    Milk::~Milk()
    {
    delete m_pBeverage;
    }

    string Milk::getDescription()
    {
    return m_pBeverage->getDescription() + " + Milk";
    }

    double Milk::cost()
    {
    return 0.10 + m_pBeverage->cost();
    }

    Soy::Soy(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    Soy::~Soy()
    {
    delete m_pBeverage;
    }

    string Soy::getDescription()
    {
    return m_pBeverage->getDescription() + " + Soy";
    }

    double Soy::cost()
    {
    return 0.15 + m_pBeverage->cost();
    }

    Whip::Whip(Beverage* pBeverage)
    {
    m_pBeverage = pBeverage;
    }

    Whip::~Whip()
    {
    delete m_pBeverage;
    }

    string Whip::getDescription()
    {
    return m_pBeverage->getDescription() + " + Whip";
    }

    double Whip::cost()
    {
    return 0.10 + m_pBeverage->cost();
    }
    int main()
    {
    Beverage* pBeverage = new Espresso();
    cout << pBeverage->getDescription() << " $" << pBeverage->cost() << endl;

    Beverage* pBeverage2 = new DarkRoast();
    pBeverage2 = new Mocha(pBeverage2);
    pBeverage2 = new Mocha(pBeverage2);
    pBeverage2 = new Whip(pBeverage2);
    cout << pBeverage2->getDescription() << " $" << pBeverage2->cost() << endl;

    Beverage* pBeverage3 = new HouseBlend();
    pBeverage3 = new Soy(pBeverage3);
    pBeverage3 = new Mocha(pBeverage3);
    pBeverage3 = new Whip(pBeverage3);
    cout << pBeverage3->getDescription() << " $" << pBeverage3->cost() << endl;
    delete pBeverage;
    delete pBeverage2;
    delete pBeverage3;
    return 0;
    }




    运行后结果如下:

    Espresso $1.99
    Dark Roast Coffee + Mocha + Mocha + Whip $1.49
    House Blend Coffee + Soy + Mocha + Whip $1.34

    参考图书:《Head First 设计模式》

  • 相关阅读:
    归并排序
    希尔排序和插入排序的关系
    相对路径与绝对路径
    httpservlet类中两个service方法
    假如生活欺骗了你
    循环队列判满和判空的两种方式
    并查集,带权,水题PKOJ1703
    字典树HDU1251
    POJ食物链,并查集,包含种类的分部
    HDU1043逆向bfs打表
  • 原文地址:https://www.cnblogs.com/osyun/p/2271314.html
Copyright © 2020-2023  润新知