定义:
装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
场景:
我们购买咖啡的时候,可以要求在其中加入各种调料,例如:蒸奶、豆浆、摩卡或覆盖奶泡,而咖啡店也会根据所加入的调料收取不同的费用,所以当我们设计订单系统的时候就需要考虑到这些调料部分啦。顾客的需求不一,如果我们针对每种配方都声明一个类得话,系统的维护将会十分头疼。此时装饰者模式就派上用场啦。我们可以根据顾客的需要动态的扩展顾客定制的咖啡,让其加上不同的调料,最终计算出顾客所需缴纳的费用。它的实现有点类似于递归,在实际使用的时候可以慢慢体会。
类图:
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 设计模式》
来源:https://www.cnblogs.com/osyun/archive/2011/12/01/2271314.html