装饰者模式

时常会遇到这样一种情况,我已经设计好了一个接口,并且也有几个实现类,但是这时我发现我设计的时候疏忽了,忘记了一些功能,或者后来需求变动要求加入一些功能,最简单的做法就是修改接口,添加函数,然后继承类中都相应的添加实现,这样做倒也没什么问题,但是如果这种变化来个好几次或者继承类非常多,那工作量可就大了。

这时大神们就发明了装饰者模式,在不修改现在有接口和实现类的基础上实现功能或者状态的添加。

从类图上看,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++实现的更多相关文章

  1. 装饰者模式 Decoration

    1.什么是装饰者模式 动态给对象增加功能,从一个对象的外部来给对象添加功能,相当于改变了对象的外观,比用继承的方式更加的灵活.当使用装饰后,从外部系统的角度看,就不再是原来的那个对象了,而是使用一系列 ...

  2. JAVA装饰者模式(从现实生活角度理解代码原理)

    装饰者模式可以动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 该模式的适用环境为: (1)在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职 ...

  3. 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)

    在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...

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

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...

  5. PHP 装饰器模式

    装饰器模式:是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能. [装饰器模式中主要角色] 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这 ...

  6. C#设计模式-装饰者模式

    在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).Access ...

  7. Java 的设计模式之一装饰者模式

    刚开始接触装饰者的设计模式,感觉挺难理解的,不够后来花了一个晚上的时间,终于有头绪了 装饰者设计模式:如果想对已经存在的对象进行装饰,那么就定义一个类,在类中对已经有的对象进行功能的增强或添加另外的行 ...

  8. 《Head First 设计模式》之装饰者模式

    作者:Grey 原文地址:http://www.cnblogs.com/greyzeng/p/5922248.html 模式名称 装饰者模式(Decorator Pattern) 需求 定义咖啡厅中的 ...

  9. DecoratorPattern(装饰器模式)

    /** * 装饰者模式 * @author TMAC-J * 总的来说,装饰者模式就是继承的应用 */ public class DecoratorPattern { interface Beans{ ...

  10. 设计模式-装饰器模式(Decrator Model)

    文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6057666.html 目录 1.概述 2.目的 3.结构组成 4.实现 5.总结 1.概 ...

随机推荐

  1. TimeHelp 获取时间戳转换类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Shar ...

  2. MHA配置文件说明

    root@192.168.0.20 ~]# cat /etc/masterha/app1.cnf [server default] manager_workdir=/var/log/masterha/ ...

  3. pgsql的同步须知

    pgsql的同步模式是根据master上的日志来做的同步,有两种同步方式,参考http://www.chinaxing.org/articles/Postgres/2012/12/14/2012-12 ...

  4. NHibernate ConfORM Mapping

    前言 昨天写了一篇fluent nhibernate通过约定的代码映射方式,NH在3.0版本以后已经集成了conform的代码映射方式,一直没注意也没使用过,今天试试怎么样. 步骤 1.通过confo ...

  5. 关于Android App开发知识体系的一个小总结

     前言 本文从热更新.异步并发.性能优化.网络请求等多个方面对Android App开发的知识体系进行了一个分类总结.欢迎大家沟通交流. 热更新 [原]热更新开源项目Tinker源码解析之Dex热更新 ...

  6. android.support.v7.internal.widget.ActionBarOverlayLayout Couldn't Be Initialized

    问题症状: Android Studio 1.2 (Build 141.1890965) 新建工程,自动build完成后,Layout Editor无法预览Layout文件,报错内容: Renderi ...

  7. buffer cache —— buffer busy waits/read by other session

    oracle提供非常精确.有效的row level lock机制,多个用户同时修改数据时,为了保护数据,以块为单位挂起锁的情况不会发生.但这不太正确.以块为单位的锁虽然不存在,但正因为oracle I ...

  8. EasyUI汇总

    easyui combobox添加清除选项按钮 <input class="easyui-combobox" name="appType" data-op ...

  9. Access空字符串和Null值

    什么是空字符串和Null值: Microsoft Access可以区分两种类型的空值.因为在某些情况下,字段为空,可能是因为信息目前无法获得,或者字段不适用于某一特定的记录.例如,表中有一个“电话号码 ...

  10. //todo 的用处

    在代码中添加 //todo 以后要做的事 可以暂时打上标记,以后再来处理. 光有这个没什么用,关键是IDE要支持,比如VS2017,只要按下 ctrl+w,t 就可以在输出窗口中显示出所有 todo的 ...