装饰者模式及C++实现
装饰者模式
时常会遇到这样一种情况,我已经设计好了一个接口,并且也有几个实现类,但是这时我发现我设计的时候疏忽了,忘记了一些功能,或者后来需求变动要求加入一些功能,最简单的做法就是修改接口,添加函数,然后继承类中都相应的添加实现,这样做倒也没什么问题,但是如果这种变化来个好几次或者继承类非常多,那工作量可就大了。
这时大神们就发明了装饰者模式,在不修改现在有接口和实现类的基础上实现功能或者状态的添加。
从类图上看,ConcreteComponent是Component原有的继承类,而Decorator装饰者类也继承与Component,这样的是让Decorator的子类也可以方便的添加Component,而不用每个子类里面都去包含一次Component。(我的理解)
这样客户端使用的时候只需要知道ConcreteDecorator就可以直接调用Decorator的operation方法了,至于operation方法是怎么实现的以及使用的Component的哪一个子类是不需要关心的,而且添加的方法addBehavior也可以直接使用。
客户端就无法依赖于抽象了,如果addBehavior的实现方法要变了,比较好的是添加新的ConcreteDecorator子类,或者继承这个ConcreteDecorator重新实现addBehavior。

常用的情况
如果需要添加新功能,但又不想修改定义好的接口或者抽象类,那么这时候就比较适合装饰模式,例如很多图形系统中的组件,就可以使用装饰模式,来让新的组件在继承现在功能的基础上添加新的功能。
装饰模式一般是针对接口或者抽象类的变化,如果是具体实现类的变化,则要考虑适用哪种模式。
优点
1.可以不用修改原有的接口,就可以实现新功能的添加。
2.装饰者可以很方便的转换原有接口中的实现,可以给装饰者指定不同的ConcreteComponent实现不同的功能。
缺点
1.复杂性增加,装饰者模式会导致许多小类的产生。
C++代码实现
#ifndef _COMPONENT_H_
#define _COMPONENT_H_ class Component
{
public:
Component();
virtual ~Component(); virtual void operation() = ;
}; class ConcreteComponent: public Component
{
public:
ConcreteComponent();
~ConcreteComponent(); void operation();
}; #endif
#include "Component.h"
#include <stdio.h> Component::Component()
{ } Component::~Component()
{ } ConcreteComponent::ConcreteComponent()
{ } ConcreteComponent::~ConcreteComponent()
{ } void ConcreteComponent::operation()
{
fprintf(stderr, "ConcreteComponent's operation!\n");
}
#ifndef _DECORATOR_H_
#define _DECORATOR_H_ #include "Component.h" class Decorator: public Component
{
public:
Decorator();
virtual ~Decorator(); virtual void operation();
virtual void setComponent(Component* pComponent); protected:
Component* mComponent;
}; class ConcreteDecorator: public Decorator
{
public:
ConcreteDecorator();
virtual ~ConcreteDecorator(); virtual void addBehavior();
}; #endif
Decorator.h
#include "Decorator.h"
#include <stdio.h> Decorator::Decorator()
{ } Decorator::~Decorator()
{ } void Decorator::operation()
{
mComponent->operation();
} void Decorator::setComponent(Component* pComponent)
{
this->mComponent = pComponent;
} ConcreteDecorator::ConcreteDecorator()
{ } ConcreteDecorator::~ConcreteDecorator()
{ } void ConcreteDecorator::addBehavior()
{
fprintf(stderr, "ConcreteDecorator's addBehavior!\n");
}
Decorator.cpp
#include "Decorator.h" int main()
{
Component* pComponent = new ConcreteComponent();
ConcreteDecorator* pConDecorator = new ConcreteDecorator();
pConDecorator->setComponent(pComponent);
pConDecorator->operation();
pConDecorator->addBehavior();
return ;
}
client.cpp
g++ -o client client.cpp Component.cpp Decorator.cpp
运行结果

装饰者模式及C++实现的更多相关文章
- 装饰者模式 Decoration
1.什么是装饰者模式 动态给对象增加功能,从一个对象的外部来给对象添加功能,相当于改变了对象的外观,比用继承的方式更加的灵活.当使用装饰后,从外部系统的角度看,就不再是原来的那个对象了,而是使用一系列 ...
- JAVA装饰者模式(从现实生活角度理解代码原理)
装饰者模式可以动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 该模式的适用环境为: (1)在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职 ...
- 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)
在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...
- 设计模式(九)装饰者模式(Decorator Pattern)
一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...
- PHP 装饰器模式
装饰器模式:是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能. [装饰器模式中主要角色] 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这 ...
- C#设计模式-装饰者模式
在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).Access ...
- Java 的设计模式之一装饰者模式
刚开始接触装饰者的设计模式,感觉挺难理解的,不够后来花了一个晚上的时间,终于有头绪了 装饰者设计模式:如果想对已经存在的对象进行装饰,那么就定义一个类,在类中对已经有的对象进行功能的增强或添加另外的行 ...
- 《Head First 设计模式》之装饰者模式
作者:Grey 原文地址:http://www.cnblogs.com/greyzeng/p/5922248.html 模式名称 装饰者模式(Decorator Pattern) 需求 定义咖啡厅中的 ...
- DecoratorPattern(装饰器模式)
/** * 装饰者模式 * @author TMAC-J * 总的来说,装饰者模式就是继承的应用 */ public class DecoratorPattern { interface Beans{ ...
- 设计模式-装饰器模式(Decrator Model)
文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6057666.html 目录 1.概述 2.目的 3.结构组成 4.实现 5.总结 1.概 ...
随机推荐
- SQL中利用脚本创建database mail.
SQL中利用脚本创建database mail 编写人:CC阿爸 2014-6-14 多话不讲,请参考以下脚本 use
- 常见的加密和解密算法—AES
一.AES加密概述 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用 ...
- 同一客户端使用多份SSH Key
创建或添加如下内容: Host example1.com HostName realname.example.com IdentityFile ~/.ssh/example1_rsa # 私钥 Hos ...
- canvas填充规则
canvas填充规则 const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); ct ...
- python实现socket上传下载文件-进度条显示
在python的socket编程中,可以实现上传下载文件,并且在下载的时候,显示进度条,具体的流程如下图所示: 1. 服务器端代码如下: [root@python 519]# cat server.p ...
- leetcode374
// Forward declaration of guess API. // @param num, your guess // @return -1 if my number is lower, ...
- URL的名称设置
1. 对于login.html 此为跳转文件, 加入了参数nid,在views.py中进行关于request.POST.get()的文件中获取 <a href='/detail?nid={{k} ...
- 当前触发事件的两种方式(onclick) 和 ('id') 获取
1. <input type='text' onclick = 'Clickon(this)'> <script> function Clickon(num){ num.sty ...
- 解决Notepad++ Plugin Manager无法加载插件的方法
今天正好安装了Notepad++,结果发现Plugin Manager里插件一个也没有,网上对应的方法都没有,最后无意间看到Plugin Manager Settings 里的提示,试了一下居然成功了 ...
- 8.3.2018 1 Quick and dirty 快而脏的快餐
Quick and dirty 快而脏的快餐 BEIJING 北京 Food delivery is a booming business. Waste is piling up, too 送餐 ...