Head First 设计模式详解之三:装饰者模式

什么是装饰者模式

装饰者模式动态地将责任附加到对象上。当需要扩展时,装饰者能提供比继承能有弹性的替代方案。当我们需要动态地添加一些功能时,可以使用装饰者模式。


举个例子

装饰者模式通过创建一个Component基类,然后让装饰者和被装饰者都继承这个基类。并在装饰者只中声明一哥被装饰者变量,从而识别要装饰的对象,并在自己的方法中,对被装饰者的方法进行功能添加。

现在我们有许多种咖啡,需要对这些咖啡添加配料,例如牛奶什么的,并且要计算咖啡和各种配料的花费。我们可以设计每种情况都设计成一个类,但是当我们的配料太多时,会发生类的爆炸,因为情况实在是太多了。装饰者模式正是合适的解决方案。

设计思想:

1、面向接口编程,而不是面向实现。我们不应该将每种搭配写死在类中。

2、对拓展开放,对修改关闭。我们应该支持之后功能的扩展,但是不允许修改我们现有的代码。

使用装饰者模式,每当我们需要一种配料时,就将对象做一层装饰,最终形成我们想要的功能。

#include <iostream>
#include <string>
using namespace std;

class Component{
public:
    virtual int cost() = 0;
    virtual string getDescription() = 0;
};

class BlackCoffee : public Component{
public:
    int cost(){ return 3;}
    string getDescription(){ return "BlackCoffe";}
};

class Decorator : public Component{
protected:
    Component* wrappedObj;
    // 如果要添加装饰类其他需要实现的方法,在此处声明
public:
    Decorator(Component* Obj){ wrappedObj = Obj; }
    virtual ~Decorator(){}
};

class Milk : public Decorator{
public:
    Milk(Component* Obj):Decorator(Obj){}
    int cost(){ return 2 + wrappedObj -> cost();}
    string getDescription(){ return wrappedObj -> getDescription() + "Milk";}
    ~Milk(){
        if(wrappedObj)
            delete wrappedObj;
    }
};

class Ice : public Decorator{
public:
    Ice(Component* Obj):Decorator(Obj){}
    int cost(){ return 1 + wrappedObj -> cost();}
    string getDescription(){  return wrappedObj -> getDescription() +"Ice";}
    ~Ice(){
        if(wrappedObj)
            delete wrappedObj;
    }
};

int main(){
    Component* Coffee = new BlackCoffee();
    Coffee = new Milk(Coffee);
    Coffee = new Ice(Coffee);
    cout << "menu is " << Coffee -> getDescription() << " ,cost is " << Coffee -> cost();
    delete Coffee;
}

输出结果为:

menu is BlackCoffeMilkIce ,cost is 6

我们可以任意扩展新的配料,而不用更改现有的代码。在mian函数中,Coffee的生成也许有点笨拙,我们可以使用工厂模式或者生成者模式,来进行新的优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值