C++设计模式之装饰者模式

来源:互联网 发布:新型农村合作医疗软件 编辑:程序博客网 时间:2024/06/16 10:49

英文叫Decorator Pattern,又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。(百度百科)
装饰模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。类与对象图如下所示:
这里写图片描述

适用情况:

  1. 需要扩展一个类的功能,或给一个类添加附加职责。
  2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
  3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
  4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

举例:

#include <iostream>using namespace std;/************************************************************************//* 问题描述:奶茶店需要设计一个系统,有不同的奶茶,例如,柃檬水,柚子茶,咖啡.....同时这些饮料可以添加不同的调料,例如,糖、牛奶,豆浆、冰块.....未来还会推出新的饮料和配料*//************************************************************************///抽象总基类class Beverage{public:    virtual double cost() = 0;    virtual string getDescription()    {        return m_description = "Unknow Beveraage";    }public:    string m_description;};//柠檬水class LemonWater : public Beverage{public:    LemonWater()    {        m_description = "柠檬水";    }    double cost()    {        return 5.0;    }    string getDescription()    {        return m_description;    }};//绿茶class GreenTea : public Beverage{public:    GreenTea()    {        m_description = "绿茶";    }    double cost()    {        return 3;    }    string getDescription()    {        return m_description;    }};//咖啡class Coffee : public Beverage{public:    Coffee()    {        m_description = "咖啡";    }    double cost()    {        return 10;    }    string getDescription()    {        return m_description;    }};//装饰者抽象基类class Decorate : public Beverage{};//装饰者 -糖class Suger : public Decorate{public:    Suger(Beverage *beverage)    {        m_beverage = beverage;    }    string getDescription()    {        return m_beverage->getDescription() + ",糖";    }    double cost()    {        return m_beverage->cost() + 5;    }private:    Beverage *m_beverage;};//装饰者 -牛奶class Milk : public Decorate{public:    Milk(Beverage *beverage)    {        m_beverage = beverage;    }    string getDescription()    {        return m_beverage->getDescription() + ",牛奶";    }    double cost()    {        return m_beverage->cost() + 5;    }private:    Beverage *m_beverage;};//装饰者 -香精class Essence : public Decorate{public:    Essence(Beverage *beverage)    {        m_beverage = beverage;    }    string getDescription()    {        return m_beverage->getDescription() + ",香精";    }    double cost()    {        return m_beverage->cost() + 5;    }private:    Beverage *m_beverage;};int main(int argc, char *args[]){    //1.来一杯柠檬水,什么都不需要    Beverage *lemenWater = new LemonWater;    cout << "饮料名称:" << lemenWater->getDescription().c_str()         <<"  价格:"<<lemenWater->cost()<< endl;    //2.来一杯加糖和香精的绿茶    Beverage *greenTea = new GreenTea;    greenTea = new Suger(greenTea);    greenTea = new Essence(greenTea);    cout << "饮料名称:" << greenTea->getDescription().c_str()         << "  价格:" << greenTea->cost() << endl;    //3.来一杯加糖,加牛奶,加香精的咖啡    Beverage *coffe = new Coffee;    coffe = new Suger(coffe);    coffe = new Milk(coffe);    coffe = new Essence(coffe);    cout << "饮料名称:" << coffe->getDescription().c_str()        << "  价格:" << coffe->cost() << endl;    getchar();    return 0;}

运行结果:
这里写图片描述

由此可见装饰者模式是在运行时动态的扩展对象功能,而继承是在编译时期就已经决定了对象的功能,因此装饰者模式比继承更为灵活。
软件设计发展的理念就是尽可能的在增加代码的可扩展性的同事避免对原有代码的修改,减轻工作负担,也就是 类应设计的对扩展开放,对修改关闭。

0 1