设计模式C++描述----10.装饰(Decorator)模式
一. 举例
我之前做过一个文件系统就叫 MyFileSys 吧,后来的话,客户想加入一些附加功能,比如压缩、加密、杀毒之类的操作,这些附加操作没有先后顺序,比如你可以先压缩再加密,也可以先杀毒再压缩,等等。
这些附加功能是可选的,有的客户要这些功能,有的不要,有的要其中的几种附加功能等等。怎么设计呢?
第一种方案:
直接修改这个独立的文件系统 MyFileSys,对于不同的客户实现不同的文件系统。

后来随着客户的增多,发现维护和修改的工作量越来越大。因为每增加一个客户就要重新生成一个类,然后把客户想要的附加功能加入,更加郁闷的是,只针对一个客户有时也是要修改很多次,客户今天要这些附加功能,明天又想加入另外一些功能,这样改来改去,维护工作量也是很大的。
第二种方案:
后来改用第二种方案,实现一个单独的附加功能类,保持原文件系统不变,这样在客户端就可以轻松的加入一些附加功能。

代码如下:
- //定义一个对象接口,可以给这些对象动态地添加职责
- class FileSys
- {
- public:
- virtual ~FileSys()
- {
- }
- virtual void Operation()
- {
- }
- protected:
- FileSys()
- {
- }
- };
- //定义一个具体的对象
- class MyFileSys:public FileSys
- {
- public:
- MyFileSys()
- {
- }
- ~MyFileSys()
- {
- }
- void Operation()
- {
- cout<<"MyFileSys operation..."<<endl;
- }
- };
- //装饰抽象类
- class Decorator:public FileSys
- {
- public:
- Decorator(FileSys* fileSys)
- {
- this->_fileSys = fileSys;
- }
- virtual ~Decorator()
- {
- delete _fileSys;
- }
- void Operation()
- {
- }
- protected:
- FileSys* _fileSys;
- };
- //压缩装饰类
- class ZipDecorator:public Decorator
- {
- public:
- ZipDecorator(FileSys* fileSys):Decorator(fileSys)
- {
- }
- ~ZipDecorator()
- {
- }
- void Operation()
- {
- _fileSys->Operation(); //首先运行以前的功能
- this->AddedZipBehavior(); //附加功能
- }
- void AddedZipBehavior()
- {
- cout<<"Added Zip Behavior...."<<endl;
- }
- };
- //杀毒装饰类
- class KillVirDecorator:public Decorator
- {
- public:
- KillVirDecorator(FileSys* fileSys):Decorator(fileSys)
- {
- }
- ~KillVirDecorator()
- {
- }
- void Operation()
- {
- _fileSys->Operation();
- this->AddedKillVirBehavior();
- }
- void AddedKillVirBehavior()
- {
- cout<<"Added Kill Virus Behavior...."<<endl;
- }
- };
- //加密装饰类
- class EncryptDecorator:public Decorator
- {
- public:
- EncryptDecorator(FileSys* fileSys):Decorator(fileSys)
- {
- }
- ~EncryptDecorator()
- {
- }
- void Operation()
- {
- _fileSys->Operation();
- this->AddedEncrypeBehavior();
- }
- void AddedEncrypeBehavior()
- {
- cout<<"Added Encrypt Behavior...."<<endl;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- //测试
- int main()
- {
- FileSys* fileSys = new MyFileSys();
- Decorator* dec1 = new ZipDecorator(fileSys); //在原文件系统上,加入压缩功能
- Decorator* dec2 = new KillVirDecorator(dec1); //在之前的基础上,加入杀毒功能
- Decorator* dec3 = new EncryptDecorator(dec2); //再加入加密功能
- dec3->Operation();
- return 0;
- }
这样之后,如果要添加附加功能,实现起来就很方便了。这种模式就是装饰模式。
二. 装饰模式
装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。

说明:
Componet,主要是定义一个接口,通过这个接口可以给这些对象(ConcreteComponent)添加职责。
Dectorator,装饰类,通过外类(ConcreteDecorator)来扩展Component 类的功能,对于Component来说,是无需知道这个抽象类的存在的。
ConcreteDecorator,具体装饰类,添加具体的附加功能。
优点:
1. 装饰类是为已有功能动态地添加更多功能的一种方式。
2. 有效地把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。
三. 问题讨论
从上图可以看到 Decorator 是继承于 Component
的,也就和 ConcreteComponent 成了兄弟了,但是 Decorator 的作用却是修饰 ConcreteComponent
的,这点好像是很怪怪的!!最说不通的是Decorator 与 Component 是没有is-a关系的!!
我个人觉得:
1. 这个继承关系,不应该是我们要重点关注的。这里使用继承主要是为了要重用 Operation() 这个接口,以达修饰的目的。
2. 重点是 Decorator 与 Component 这个组合关系。装饰类里有一个Component 指针,正是由于它的存在才能修饰到具体的 Component 对象。
设计模式C++描述----10.装饰(Decorator)模式的更多相关文章
- 《Head First 设计模式》ch.3 装饰(Decorator)模式
设计原则 类应该对修改关闭,对扩展开放(开放-关闭原则).在每个地方使用开放-关闭原则是一种浪费,也没有必要,因为这通常会引入新的抽象层次,增加代码复杂度.需要把注意力集中在设计中最有可能改变的地方. ...
- 设计模式(八)装饰器模式Decorator(结构型)
设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...
- php设计模式课程---7、装饰器模式如何使用
php设计模式课程---7.装饰器模式如何使用 一.总结 一句话总结: 装饰器的核心是获取了文章类整个类,而不是获取了文章内容,有了这个文章类,我想给你加多少装饰就给你加多少装饰(将文章这个类封装进去 ...
- 设计模式(九)——装饰者模式(io源码分析)
1 星巴克咖啡订单项目(咖啡馆): 1) 咖啡种类/单品咖啡:Espresso(意大利浓咖啡).ShortBlack.LongBlack(美式咖啡).Decaf(无因咖啡) 2) 调料:Milk.So ...
- 大型Java进阶专题(八)设计模式之适配器模式、装饰者模式和观察者模式
前言 今天开始我们专题的第八课了.本章节将介绍:三个设计模式,适配器模式.装饰者模式和观察者模式.通过学习适配器模式,可以优雅的解决代码功能的兼容问题.另外有重构需求的人群一定需要掌握装饰者模式. ...
- 装饰(Decorator)模式
1.装饰(Decorator)模式 动态给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更为灵活.Component是定义一个对象接口.可以给这些对象动态地添加职责.Concre ...
- 设计模式之第10章-桥接模式(Java实现)
设计模式之第10章-桥接模式(Java实现) “一入软件深似海,从此早睡是路人.黑夜给了我黑色的眼睛,我却用他去寻找八阿哥.”“怎么了,又来那么多的感慨啊.”“还能有什么啊,老板是说让换个APP做,这 ...
- ④ 设计模式的艺术-10.装饰(Decorator)模式
职责 装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对 ...
- 【设计模式 - 9】之装饰者模式(Decorator)
1 模式简介 装饰者模式允许向一个现有的对象添加新的功能,同时又不改变其结构. 装饰者模式的思路是用"调料"对象将原始对象进行层层包裹,同时其属性.动作层层传递,达到最终 ...
随机推荐
- redis分布式锁-WATCH锁(废弃)
使用watch构建锁的代码结构.(最着负载不断增加,系统完成一次加锁操作,重试次数不断加大) pine=conn.pineline while pine.watch if xxx pine.unwat ...
- freemarker常用属性
1.th:action 定义后台控制器的路径,类似<form>标签的action属性. 示例如下. <form id="login" th:action=&quo ...
- win10 cnpm安装完之后一直说不是内部命令的原因
找到cnpm的默认安装路径 一般默认的是 D:\Program Files\nodejs\node_modules 然后添加环境变量中 win10是在系统环境变量中切记不是在用户变量中.保存之后,重新 ...
- Spark 学习笔记之 共享变量
共享变量: 共享变量通常情况下,当向Spark操作(如map,reduce)传递一个函数时,它会在一个远程集群节点上执行,它会使用函数中所有变量的副本.这些变量被复制到所有的机器上,远程机器上并没有被 ...
- 直通BAT面试题库锦集
01 python面试题(汇总) 02 面向对象 03 网络和并发编程 04 模块 05 设计模式 06 前端 07 Django框架 08 Flask 09 tornado 10 DB
- k8s中负载均衡器【ingress-nginx】部署
在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的.为了使外部的应用能够访问集群内的服务,在Kubernetes 目前 提供了以下几种方案: Node ...
- 洛谷 1552 [APIO2012]派遣
题目背景 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿. 题目描述 在这个帮派里,有一名忍者被称之为Master.除了Master以外,每名忍者都有且仅有一个上级.为保密 ...
- html隐写术,使用摩尔兹电码/莫尔兹电码存储信息 水波纹样式 Morse code
html水波纹样式,源码直接下载,代码有注释教程,小白可以看懂. 动画啥的都做好了,效果我觉得还不错 网上文章看到xbox 工程师使用隐写术,在界面的右下角放上了含有用户激活码的水波纹样式,一般人还真 ...
- top命令之性能分析
top命令详解 当前时间20:27:12 当前系统运行时间3:18秒 1个用户 系统负载平均长度为0.00,0.00,0.00(分别为1分钟.5分钟.15分钟前到现在的平均值) 第二行为进程 ...
- axios学习和使用
网络请求的方式 传统的Ajax,基于XMLHttpRequest(不推荐) 配置调用方式混乱(回调地狱) jQuery-Ajax (在vue开发中不推荐) 相对于传统的Ajax非常好用 但是jQuer ...