DECORATOR中文的意思是装饰,该模式的动机是帮助对象动态的添加一些功能。它强调是为对象而不是为类添加功能。为类添加功能最有效的方式是通过继承来实现,但继承的缺点是不够灵活。下面我们还是通过例子来理解该模式。

十年生死两茫茫,不思量,自难忘。 
    千里孤坟,无处话凄凉。 
    纵使相逢应不识,尘满面,鬓如霜。 
     
    夜来幽梦忽还乡,小轩窗,正梳妆。 
    相顾无言,惟有泪千行。 
    料的年年断肠处,明月夜,短松冈。 
     
     挺喜欢这首词的,是我能背下来的不多的几首词中的一首。这是苏东坡为亡妻王弗写的一首悼亡诗。王弗十六岁时嫁给苏轼,婚后夫妻恩爱。苏轼的《亡妻墓志铭》中写到:“见轼读书,则终日不去。”颇有“红袖添香夜伴读”之味。可惜正如苏轼的《明月几时有》中写的一样:“人有悲欢离合,月有阴晴圆缺,此事古难全。”王氏于二十七岁时病逝,苏轼悲痛万分。十年后的一个夜晚,苏轼又一次在梦中梦到了与妻子往日的缠绵,醒来后不禁泪下,写下了这首词。 
    前两天,和一兄弟网上聊天。他说自己陷入情网,无法自拔,痛苦万分。问他什么原因?他说自己爱上了一个女孩,但人家已经有了男朋友;看着年龄越来越大,找到自己合适的伴侣是越来越难。为了给他雪上加霜,我劝他死心吧,找到合适的概率太小;不如等到那天混的可以了,有房子后,发个征婚启示什么的,然后就可以直接结婚了。他坚决的拒绝了我给他的友好建议,说看到很多结婚的朋友,为了鸡毛蒜皮的小事而吵架,一点意思都没有;与其这样,还不如自己一个人。是啊,随着工业文明的进步,人的神经也被不断的拉紧,少了农耕时代的悠闲。我们的生活越来越匆忙,少了欣赏美的情趣,生活中的点点滴滴的美,有多少人可以体验得到?“小轩窗,正梳妆”,古人可以体会得到的美,而在我们的字典里能找到吗?为了些须小事而吵架分离,婚姻不再是“围城”,令城外的我们也忘而却步。很多人都在等待,等待那份不会因物质而庸俗化的爱情,能等到吗?“但愿人长久,千里共婵娟”,将此祝福天下所有期望这份爱情的人。 
    好了,我们来描述我们的例子吧。考虑一下美女梳妆的情景,她会盘弄自己的头发,填加首饰在自己头上,可能还有耳环一类的东西。但每个美女身上的饰物并不相同,我们为美女提供一个类的话,如何可以做到让她们的饰物各不相同呢?好的,我们还是一步一步来,首先抽象出一个美女类:


 
    这个类比较简单,就是画一个美女出来(不好意思,这里仍然是用文字意思一下,不熟悉图象处理;真希望能真正画一个出来,什么时候有时间好好学学)。我们再来看如何帮美女填加饰物,仍是先看传统的方式: 
 
     那么需要填加这样的变量m_IsHasHair(什么,美女可以没有头发?当然可以,不信可以找金庸的《笑傲江湖》来看看),m_IsHasNeaklace(项链),m_IsEarbob(耳环)。那么我们的Draw的实现就需要根据不同的条件来实现,大概的代码如下:

Void Draw()
{   
    ……画一个美女    
    If( m_IsHasHair){      
        …….  
    }  
    
    If ( m_IsHasNeakLace){   
        ……..  
    }  
    
    If ( m_IsEarbob){
           …….. 
    }
}

还是结构化的东西,我们需要考虑的问题是:当新的饰物需要填加到类中的时候,我们该如何处理?再次强调面向对象的基本原则:一个模块对扩展应该是开放的,对修改应该是关闭的。如果按现在的做法,我们不得不再次打开Draw为它添加新的条件,实现新的功能。这个方案被否决,那么我优先考虑到的还是继承,看它能不能完成我们的功能?


 
     如上类图,我们试图使用继承的方法来实现该功能。当新加装饰类型的时候,是可以做到不需改变以前的代码。但新的问题又来,当一个美女既有头发又有项链的时候,我们该怎么办。那么通过继承的方法就是新加一个类:BeautyWithHairAndNeakLace,如果一个一个条件组合下去,类又失去了控制,又是类爆炸现象。简单的继承无法完成我们的功能。还好,如果你知道了Decorator模式,问题就会变的简单起来。我们首先来看看Decorator模式的类图。 
 
     对该类图,做一些说明: 
    1,我们需要为我们要用到的类和它所需要的包装类提供一个共同的接口:Component。 
    2,ConcreteComponent是我们要用到的类,就是需要为该类的对象动态的填加一些功能进去。 
    3,Decorator是我们要用到的包装类,它也应该是一个抽象类,我们是通过它的子类来实现对ConcreteComponent的包装。每个Decorator子类的实例都应该拥有一个指向Component的指针或引用。 
    4,ConcreteDecoratorA和ConcreteDecoratorB是我们用来包装的实类,它拥有一个指向Component的实例。我们可以在该类中填加新的类型和方法,但这些类型和方法只能在类内部使用,因为该类的调用是通过Component接口来实现的。 
     好了,看完该类图,你是否对该模式还是不清楚?没关系,看到实际的代码后,一切就清晰了。我们再按该模式来设计我们的美女类图: 
 
     帮我们的美女抽象出一个接口:BeautyInterface。Beauty继承自BeautyInterface是我们实际要用到的类。而BeautyDecorator是我们抽象出的装饰类。Hair,Necklace,Earbob是要具体用来装饰的类,可以看到他们重载了Draw,调用接口的Draw并且填加一些自己的功能进去。具体该如何用呢?来看代码。

//美女接口    
class BeautyInterface    
{    
public:    
    virtual void Draw() = 0;
};

//美女实类    
class Beauty : public BeautyInterface    
{    
public:        
    void Draw()
    { 
        cout << "This is a beauty!" << endl;
    }    
};

//美女装饰类    
class BeautyDecorator : public BeautyInterface    
{    
public:        
    virtual void Draw() = 0;    
};

//头发类    
class Hair : public BeautyDecorator    
{    
private:        
    BeautyInterface *m_pBeauty;

public:        
    Hair(BeautyInterface *pBeauty):m_pBeauty(pBeauty){}        
    
    void Draw()        
    {             
        m_pBeauty->Draw();    
        DrawHair();        
    }

private:        
    void DrawHair()    
    {            
        cout << "Hi,this is my beautiful hair!" << endl;    
    }    
};

//项链类    
class Neaklace : public BeautyDecorator
{    
private:    
    BeautyInterface *m_pBeauty;    
public:        
    Neaklace(BeautyInterface *pBeauty):m_pBeauty(pBeauty){}        
    
    void Draw()        
    {             
        m_pBeauty->Draw();            
        DrawNeaklace();        
    }    
private:
    void DrawNeaklace()    
    {            
        cout << "Hi,look at my neaklace!" << endl;
    }    
};

//耳环类    
class Earbob : public BeautyDecorator    
{    
private:    
    BeautyInterface *m_pBeauty;

public:        
    Earbob(BeautyInterface *pBeauty):m_pBeauty(pBeauty){}    
    void Draw()    
    {         
        m_pBeauty->Draw();        
        DrawEarbob();    
    }

private:    
    void DrawEarbob()    
    {        
        cout << "Hi,look at my Earbob!" << endl;    
    }    
};

好了,这就是我们要实现的类代码。我们需要注意的是Hair等装饰类的构造函数,需要初始化一个BeautyInterface接口指针。 
        Hair(BeautyInterface*pBeauty):m_pBeauty(pBeauty){}

我们再来看看该类的具体应用:

int main(int argc, char* argv[])
{ 
    BeautyInterface *pBeauty = new Earbob(new Neaklace(new Hair(new Beauty))); 
    pBeauty->Draw();    
    delete pBeauty;  
    return 0;
}

编译后的运行结果如下: 
 

C++ decorator(装饰)模式相关推荐

  1. 06Decorator(装饰)模式

    技术交流QQ群:1027579432,欢迎你的加入! 1.单一职责模式 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀.同时充斥着重复代码,这时候的关键 ...

  2. 设计模式的征途—10.装饰(Decorator)模式

    虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...

  3. Java —— Decorator 装饰器模式

    文章目录 Java -- Decorator 装饰器模式 简介 用处 简单例子 结构 代码 涉及角色 相关的设计模式 应用实例 优点 缺点 使用场景 注意事项 代码 Java -- Decorator ...

  4. 设计模式:Decorator(装饰者模式)

    Decorator(装饰者模式) 装饰模式的定义与特点 装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式 ...

  5. 一文读懂 @Decorator 装饰器——理解 VS Code 源码的基础

    作者:easonruan,腾讯 CSIG 前端开发工程师 1. 装饰器的样子 我们先来看看 Decorator 装饰器长什么样子,大家可能没在项目中用过 Decorator 装饰器,但多多少少会看过下 ...

  6. Decorator装饰者【C++实现】

    Decorator装饰者 文章目录 Decorator装饰者 一.简介 二.应用场景 三.优缺点 (3-1)优点 (3-2)缺点 四.Decorator装饰者模式结构 (4-1)设计核心 (4-2)结 ...

  7. Python中的decorator装饰器使用方法

    装饰器的运用是Python编程中的一项高级技巧,这里由浅入深,整理了12步入门Python中的decorator装饰器使用方法,需要的朋友可以参考下 装饰器(decorator)是一种高级Python ...

  8. 聊聊在Vue项目中使用Decorator装饰器

    戳蓝字" Web前端严选 " 关注我们哦 ! 前言 初衷: 前几天我在公司其它Vue项目中,发现了是用Decorator装饰器模式开发的,看起来整体代码还不错,于是就做了一下笔记分 ...

  9. Python 中的闭包、匿名函数、decorator 装饰器与python的偏函数

    Python中的闭包 def calc_sum(lst):def lazy_sum():return sum(lst)return lazy_sum 像这种内层函数引用了外层函数的变量(参数也算变量) ...

  10. JS Decorator —— 装饰器(装饰模式)

    本文只浅析类装饰器和方法装饰器,其他原理相似,暂不赘述. 关于@Component类装饰器及vue-class-component源码可查看本人另一篇:源码探秘之 vue-class-componen ...

最新文章

  1. 图像处理时一些卷积核子函数的生成
  2. Scala基础教程(八):模式匹配、正则表达式
  3. VTK:平面源用法实战
  4. springcloud 错误: 找不到或无法加载主类
  5. Qt4_在Qt设计师中集成自定义窗口部件
  6. web前端 html+css+javascript网页设计实例 家乡网站制作
  7. MySQL基础练习题(带答案)
  8. MATLAB学习八(二):标准差std
  9. 统计学(第七版)贾俊平课后习题数据
  10. 用Python模拟QQ界面之QQ登录界面的奥秘
  11. 半导体封装测试英语词汇量的软件,半导体英语
  12. Failed to obtain JDBC Connection
  13. 计算机能不能升级固态硬盘,笔记本升级固态硬盘后会怎样?秒懂
  14. 应用在夜灯领域的环境光测距感器芯片
  15. pytorch之models
  16. Mac SCP简单使用(Mac WinSCP)
  17. 深度学习如何训练出好的模型
  18. Linux中suid提权
  19. docker与宿主机共享内存通信
  20. 微信多开器 Python窗口编程 隔离运行(一)

热门文章

  1. ABCD过桥题的规律
  2. 413:Calling Extraterrestrial Intelligence Again(翻译 )
  3. ACM-ICPC 2018 沈阳赛区网络预赛 J Ka Chang 分块
  4. ElasticSearch之HTTP索引操作和文档操作
  5. 蓝桥杯六届 八题 移动距离JAVA题解
  6. Python入门技巧
  7. 【MySQL】索引的使用和优化
  8. 通过强化学习和官方API制作《星露谷物语》的自动钓鱼mod
  9. Centos8安装完mysql
  10. 200亿元输血求生,中芯国际希望几何?