设计模式之9 - 装饰模式Decorator

        我们经常会遇到这种问题,当一个类出现非常多的选择,比如 咖啡,要加 糖、抹茶、香草、牛奶……,那么多调味品,在这种情况下,考虑通过继承的方式是否合理?你会得到 很多种咖啡类,牛奶咖啡、抹茶咖啡、牛奶椰蓉咖啡、香草黑糖咖啡、曲奇巧克力蛋奶咖啡……,好像很不靠谱对吧?

        发现了 上面的 子类爆炸问题 后,你可能会问,我需要定义那么多的子类吗? 咖啡就是咖啡,其他的只是酌料而已。

        装饰者模式 相当于在类外面加上包装,生成新的类,这样做的好处 一是 减少了子类的数量(没有了组合类),二是可以在运行时动态组合,更加灵活。

        

        还是以 咖啡为例,通过代码来进行说明:

// Caffe抽象基类 - Component
class ICaffe
{
public:
    virtual float getPrice();
};

// Caffe实现类 - ConcreteComponent
class Caffe : public ICaffe
{
public:
    virtual float getPrice() { return 10; };
};
// Decortaor
class Decorator : public ICaffe
{
public:
    Decorator(Icaffe* pComponent)
        : m_pComponent(pComponent)
    {
    }
public:
    virtual float getPrice()
    {
         return m_pComponent->getPrice();
    }
protected:
    ICaffe* m_pComponent;
};

// ConcreteDecorator
class MochaCaffe : public Decorator
{
public:
    MochaCaffe(Icaffe* pComponent)
        : Decorator(pComponent)
    {
    }
public:
    virtual float getPrice()
    {
         return 0.5 + m_pComponent->getPrice();
    }
};
        装饰者模式 通过相同的抽象基类,能够实现多层的包装,这样做的缺点是 其内容定义往往不是很清晰,就好像我们收到一个程序员朋友寄来的礼物,拆开 天猫的塑料袋,里面是个纸箱子,拆开纸箱子里面是一个盒子,拆开盒子发现里面是一个信封,拆开信封发现里面有张纸,清晰得写着四个大字:“Hello World!”

        尽管大家众说纷纭,但作者并不推崇 装饰者模式,相反,在复杂性和可读性之间抉择,我认为这是一个失败的模式,也许下面的实现会更容易理解:

// Caffe类
class Caffe
{
public:
    virtual float getPrice() { return 10; }
};

// 修饰组件类
enum Dressing_Type { 抹茶,糖,辣椒,牛奶,香草,巧克力,奶昔,… }
class Dressing
{
public:
    Dressing_Type type;  // 修饰类型
    float price;
};

// 具体实现类
class DressedCaffe : public Caffe
{
public:
    virtual float getPrice()
    {
         // 遍历vector求和
    }
protected:
    Caffe             m_Caffe;
    vector<Dressing>  m_vecDressing;
};
        只需要扩展Dressing的属性定义即可,这里不去比较哪种方案的优劣,其实每个人都有自己的代码习惯,符合自己的才是最好的,PS:设计模式里面真正应用最多的也就那么几种,用之前先要考虑这是否必要,强用设计模式 着实是初学者 一个非常大的误区!
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值