设计模式——装饰者模式(c++)

    xiaoxiao2025-10-27  9

    装饰者模式用来解决的问题是:主体类(例如,下文中的各种咖啡)有多种装饰属性(例如,下文中的milk,whip等),而且装饰属性可以任意组合叠加,如果通过继承主体类来添加属性,子类的数量将非常庞大,不易维护。

    装饰者模式的核心在于——用“组合”代替“继承”!如果依赖继承,类的行为只能在编译时静态决定。但是利用组合,再加上多态,就可以使类的行为在运行是动态决定,提高了代码的可复用性。

    在GOF《设计模式》中将装饰者模式定义为:动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,装饰者模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)。

    在《HeadFirst设计模式》中装饰者模式的定义为:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    装饰者模式遵守开闭原则——“对扩展开放,对修改关闭”。也就是说,可以实现在不修改类的同时,对类进行扩展。

    装饰者模式中,同时使用了继承和组合两种方式,这是比较特殊的地方(一般来讲,继承和组合是不同时使用的)。装饰者模式中,利用继承达到“类型匹配”,而不是“继承行为”。

    下面通过一个例子来说明装饰者模式(来自《HeadFirst设计模式》,将其用c++实现)。

    一个咖啡店的点单系统中,有多种咖啡:HouseBlend、DarkRoast、Defaf、Espresso...,购买咖啡时,顾客还可能要求加入各种配料:Milk、Soy、Mocha、Whip,顾客点单后需要根据所点的咖啡和配料计算出价格。此外,咖啡的种类和配料的种类随时可能增加,而且价格也随时可能会变化。下面给出两种设计方案,并说明它们的优缺点。

    方案一:利用继承来扩展。

    从上面的类图可以看到,子类的数量将非常非常多,代码重复严重,修改和维护极为不便。

    方案二:装饰者模式,用组合代替继承。

    #ifndef BEVERAGE_H  #define BEVERAGE_H #include <string> using std::string; class Beverage { public: Beverage(const string& describe,int cost):m_describe(describe),m_cost(cost){} virtual ~Beverage() {} virtual string getDescribe() const { return m_describe; } virtual int getCost() const { return m_cost; } protected: string m_describe; int m_cost; }; class HouseBlend:public Beverage { public: HouseBlend(const string& describe="It is a cup of HouseBlend", int cost=100) :Beverage(describe, cost) {} }; class DarkRoast:public Beverage { public: DarkRoast(const string& describe = "It is a cup of DarkRoast", int cost=200) :Beverage(describe, cost) {} }; class Espresso :public Beverage{ public: Espresso(const string& describe = "It is a cup of Espresso", int cost=300) :Beverage(describe, cost) {} }; class Decaf :public Beverage { public: Decaf(const string& describe = "It is a cup of Decaf", int cost = 400) :Beverage(describe, cost) {} }; #endif

    #ifndef DECORATOR_H #define DECORATOR_H #include "Beverage.h" #include <iostream> using std::cout; using std::endl;   class Decorator :public Beverage { public: virtual ~Decorator() {} Decorator(Beverage *pBeverage,string describe, int cost) :Beverage(describe, cost), m_pBeverage(pBeverage) {} virtual string getDescribe() const { return m_pBeverage->getDescribe() + "+" + m_describe; } virtual int getCost() const { return m_pBeverage->getCost() + m_cost; } private: Beverage *m_pBeverage; }; class Milk :public Decorator{ public: Milk(Beverage *pBeverage, const string& describe="Milk", int cost=1) :Decorator(pBeverage, describe, cost) {} }; class Mocha :public Decorator { public: Mocha(Beverage *pBeverage, const string& describe="Mocha", int cost=2) :Decorator(pBeverage, describe, cost) {} }; class Soy :public Decorator { public: Soy(Beverage *pBeverage, const string& describe="Soy", int cost=3) :Decorator(pBeverage, describe, cost) {} }; class Whip :public Decorator { public: Whip(Beverage *pBeverage, const string& describe="Whip", int cost=4) :Decorator(pBeverage, describe, cost) {} }; #endif

    #include "Decorator.h" #include "Beverage.h" #include <iostream> #include <string> using std::cout; using std::endl; using std::string; int main() { Beverage *pB1 = new Whip(new Mocha(new Espresso())); cout << pB1->getDescribe() << endl; cout<< "$" << pB1->getCost()<<endl; system("pause"); return 1; }

    转载请注明原文地址: https://ju.6miu.com/read-1303568.html
    最新回复(0)