c++設計模式:裝飾者模式(Decorator Pattern)
阿新 • • 發佈:2019-01-29
定義:
裝飾者模式動態的將責任附加到物件上。若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。
場景:
我們購買咖啡的時候,可以要求在其中加入各種調料,例如:蒸奶、豆漿、摩卡或覆蓋奶泡,而咖啡店也會根據所加入的調料收取不同的費用,所以當我們設計訂單系統的時候就需要考慮到這些調料部分啦。顧客的需求不一,如果我們針對每種配方都宣告一個類得話,系統的維護將會十分頭疼。此時裝飾者模式就派上用場啦。我們可以根據顧客的需要動態的擴充套件顧客定製的咖啡,讓其加上不同的調料,最終計算出顧客所需繳納的費用。它的實現有點類似於遞迴,在實際使用的時候可以慢慢體會。
類圖:
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:publicBeverage { 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 設計模式》