首先什么是“策略模式”:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成之类更为灵活。(大话设计模式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; }
结果:
装饰模式可以灵活地为对象增加职责,是开放-封闭原则的很好体现之一!