装饰者模式(decorator pattern)

装饰者模式:

    能够动态地往一个类中添加新的行为。相比继承是在编译时添加行为,装饰模式是在运行时添加行为。

星巴克咖啡是讲述装饰者模式的一个很好的例子。

    假设现在有两种咖啡:HouseBlend、DarkRoast,同时有两种调料:Milk、Mocha。那么此时我们可以给顾客提供以下咖啡:

HouseBlend、HouseBlendWithMilk、HouseBlendWithMocha、HouseBlendWithMilkandMocha、

DarkRoast、DarkRoastWithMilk、DarkRoastWithMocha、DarkRoastWithMilkandMocha。如果每种搭配都是一个类,那么随着咖啡和调料种类的增加,将会出现类爆炸:

此时装饰者模式应运而生,结构图如下:

C++实现:

class Coffee {
public:
    virtual double getCost() = 0;
    virtual string getDescription() = 0;
};

class HouseBlend : public Coffee {
public:
    double getCost() { return 1.24; }
    string getDescription() { return "HouseBlend"; }
};

class DarkRoast : public Coffee {
public:
    double getCost() { return 2.73; }
    string getDescription() { return "DarkRoast"; }
};

class CoffeeDecorator : public Coffee {
private:
    Coffee *decoratedCoffee;
public:
    CoffeeDecorator(Coffee *c): decoratedCoffee(c) {}
    double getCost() { return decoratedCoffee->getCost(); }
    string getDescription() { return decoratedCoffee->getDescription(); }
};

class Milk : public CoffeeDecorator {
public:
    Milk(Coffee *c): CoffeeDecorator(c) {}
    double getCost() { return CoffeeDecorator::getCost() + 0.5; }
    string getDescription() {return CoffeeDecorator::getDescription() + ", Milk"; }
};

class Mocha : public CoffeeDecorator {
public:
    Mocha(Coffee *c): CoffeeDecorator(c) {}
    double getCost() { return CoffeeDecorator::getCost() + 0.7; }
    string getDescription() {return CoffeeDecorator::getDescription() + ", Mocha"; }
};

int main()
{
    Coffee *pc = new HouseBlend;
    cout << "description: " << pc->getDescription() << "  cost: " << pc->getCost() << endl;
    pc = new Milk(pc);
    cout << "description: " << pc->getDescription() << "  cost: " << pc->getCost() << endl;
    pc = new Mocha(pc);
    cout << "description: " << pc->getDescription() << "  cost: " << pc->getCost() << endl;
    delete pc;
}

装饰者模式的一个特征是:装饰者和被装饰对象具有相同的超类型。

reference:

Decorator in C++: Before and after

 

posted @ 2015-08-17 20:05  Sawyer Ford  阅读(204)  评论(0编辑  收藏  举报