首先什么是“策略模式”:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成之类更为灵活。(大话设计模式P48)


装饰模式UML类图:

大话设计模式学习笔记-装饰模式(c++描述)_C++

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;
}


结果:

大话设计模式学习笔记-装饰模式(c++描述)_设计模式_02


装饰模式可以灵活地为对象增加职责,是开放-封闭原则的很好体现之一!