首先什麼是“策略模式”:動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成之類更為靈活。大話設計模式P48)
裝飾模式UML類圖:
1、其中Component類定義了一個對象接口,可以給這些對象動態添加職責
2、ConcreteComponent類定義了具體的對象,這些對象是被添加職責
3、Decorator類定義了裝飾類的接口,繼承於Component類,用於給對象添加職責
3、ConcreteDecorator類是裝飾類的具體對象,這些實現類可以額外添加自己的特性或者行為,來到給對象添加職責,靈活性比繼承要好。
代碼實現:
//Component class Component { public: virtual void Operation() = 0; }; //ConcreteComponent class ConcreteComponent : public Component { public: void Operation() { //具體對象的操作 } }; //Decorator class Decorator : public Component { public: void SetComponent(Component *pc) { this->component = pc; } void Operation() { if (component) { component->Operation(); } } protected: Component *component; }; //ConcretrDecoratorA class ConcretrDecoratorA : public Decorator { public: void Operation() { Decorator::Operation(); addedState = ""; cout << addedState; } private: string addedState; //增添特性 }; //ConcretrDecoratorB class ConcretrDecoratorB : public Decorator { public: void Operation() { Decorator::Operation(); AddedBehavior(); //do A } private: void AddedBehavior() { //do B } //增添行為 };
客戶端:
int main() { ConcreteComponent *pc = new ConcreteComponent(); ConcretrDecoratorA *pda = new ConcretrDecoratorA(); ConcretrDecoratorB * pdb = new ConcretrDecoratorB(); pda->SetComponent(pc); pdb->SetComponent(pda); pdb->Operation(); return 0; }
下面以飲料添加輔料來實戰演練一下:
一杯普通的咖啡只要5元,添加奶泡1元),添加巧克力2元),添加方糖1.5元).....
所以以飲料類作為對象接口,有各種飲料的具體對象咖啡、奶茶、牛奶等等),和各種輔料類裝飾類),有奶泡,巧克力等等....
飲料類:
//飲料類 class Beverage { public: Beverage() {} Beverage(string n, double c) : name(n), cost(c) {} virtual void show() { cout << name; } virtual double GetCost() { return cost; } protected: string name; double cost; }; //咖啡飲料,具體實現類 class Coffee : public Beverage { public: Coffee() : Beverage("咖啡", 5) {} }; //奶茶飲料,具體實現類 class MilkTea : public Beverage { public: MilkTea() : Beverage("奶茶", 6) {} };
輔料類:
//裝飾類,輔料 class Decorator : public Beverage { public: void SetComponent(shared_ptr<Beverage> b) { beverage = b; } void show() { if (beverage) beverage->show(); } double GetCost() { if (beverage) return beverage->GetCost(); } protected: shared_ptr<Beverage> beverage; }; //輔料類,奶泡 class MilkFoam : public Decorator { public: void show() { Decorator::show(); cout << " + " << "奶泡"; } double GetCost() { return Decorator::GetCost() + 1; } }; //輔料類,巧克力 class Chocolate : public Decorator { public: void show() { Decorator::show(); cout << " + " << "巧克力"; } double GetCost() { return Decorator::GetCost() + 2; } }; //輔料類,方糖 class Suger : public Decorator { public: void show() { Decorator::show(); cout << " + " << "方糖"; } double GetCost() { return Decorator::GetCost() + 1.5; } };
客戶端代碼:
int main() { cout << "我要咖啡加方糖" << std::endl; shared_ptr<Beverage> coffee(new Coffee()); shared_ptr<Decorator> suger(new Suger()); suger->SetComponent(coffee); suger->show(); cout << "\n總價格: " << suger->GetCost() << std::endl; cout << "我要奶茶,加奶泡和巧克力" << std::endl; shared_ptr<Beverage> milktea(new MilkTea()); shared_ptr<Decorator> milkfoam(new MilkFoam()); shared_ptr<Decorator> chocolate(new Chocolate()); milkfoam->SetComponent(milktea); chocolate->SetComponent(milkfoam); chocolate->show(); cout << "\n總價格: " << chocolate->GetCost() << std::endl; return 0; }
結果:
裝飾模式可以靈活地為對象增加職責,是開放-封閉原則的很好體現之一!
本文出自 “加和文的世界” 博客,請務必保留此出處http://xuyjun.blog.51cto.com/7470650/1304165