装饰者模式定义
动态地将责任附加到对象上,若要扩展功能,装饰者模式提供了比继承更具有弹性的替代方案。
主要包含四部分:
抽象组件,抽象装饰者,具体组件,具体装饰者
实例:咖啡点餐机实现
#include "bits/stdc++.h"using namespace std;enum SIZE {BIG = 0, MID = 1, SMALL = 2};// 饮料类class Beverage {public:virtual string getDescription() {return description;}virtual double cost() = 0;;virtual SIZE getSize() = 0;private:string description = "Unknown Beverage";SIZE cup_size{};};// 开始制作第一种饮料,比如浓缩咖啡Espressoclass Espresso : public Beverage {public:~Espresso() = default;explicit Espresso(SIZE size) {description = "Espresso";cup_size = size;}string getDescription() override {return description;}double cost() override {return 1.99;}void setSize(SIZE i) {//设置咖啡杯的大小cup_size = i;}SIZE getSize() override {//获得咖啡杯的大小return cup_size;}private:string description;SIZE cup_size;};// 第二种饮料 HouseBlendclass HouseBlend : public Beverage {public:~HouseBlend() = default;explicit HouseBlend(SIZE size) {description = "House Blend Coffee";cup_size = size;}string getDescription() override {return description;}double cost() override {return 0.89;}void setSize(SIZE i) {//设置咖啡杯的大小cup_size = i;}SIZE getSize() override {//获得咖啡杯的大小return cup_size;}private:string description;SIZE cup_size;};// 由于装饰者和被装饰者必须是一样的类型,也就是具有共同的超类,因此抽象装饰者继承自抽象组件,以达成类型匹配。// 抽象装饰者,调料,class Condiment : public Beverage {public:virtual string getDescription() = 0;};// 现在有了抽象组件Beverage 和具体组件Espresso等,也有了抽象装饰者Condiment,现在实现具体装饰者//摩卡class Mocha : public Condiment {public:~Mocha() = default;explicit Mocha(Beverage *temp) {this->coffee = temp;}string getDescription() override {return coffee->getDescription() + ", Mocha";}SIZE getSize() override {return coffee->getSize();}double cost() override {//根据咖啡杯的大小决定加摩卡的价格double cost = coffee->cost();switch (getSize()) {case SMALL:cost += 0.20;break;case MID:cost += 0.25;break;case BIG:cost += 0.30;break;default:cout << "There is not this SIZE" << endl;}return cost;}private:Beverage *coffee;};//奶泡class Whip : public Condiment {public:~Whip() = default;explicit Whip(Beverage *temp) {this->coffee = temp;}string getDescription() override {return coffee->getDescription() + ", Soy";}SIZE getSize() override {return coffee->getSize();}double cost() override {double cost = coffee->cost();switch (getSize()) {case SMALL:cost += 0.10;break;case MID:cost += 0.15;break;case BIG:cost += 0.20;break;default:cout << "There is not this SIZE" << endl;}return cost;}private:Beverage *coffee;};int main() {cout<<">>>>>>>>>>>>>> Decorator Mode>>>>>>>>>>>>>";// 大杯浓缩咖啡Beverage *beverage1 = new Espresso(BIG);cout << beverage1->getDescription() << " $" << beverage1->cost() << endl;// 中杯 星巴克+ 两份摩卡 + 奶泡Beverage *beverage2 = new HouseBlend(MID);beverage2 = new Mocha(beverage2);beverage2 = new Mocha(beverage2);beverage2 = new Whip(beverage2);cout << beverage2->getDescription() << " $" << beverage2->cost() << endl;return 0;}
总结
1.装饰者和被装饰者必须是同一类型,这是装饰者模式的关键,在这里是利用继承达到“类型匹配”,而非继承行为。
2.装饰者和被装饰者进行组合时,就在装饰者中加入了新的行为,行为不是来自继而是来自组合。
3.依赖继承的行为,在编译时静态决定。利用组合,可以把装饰者混合使用,并且是在运行时决定行为。

