《head first》中 的样例:咖啡店有各种咖啡饮料,能够往咖啡里面加各种调料变成还有一种饮料。假设使用继承的方式来为每一种饮料设计一个类,代码的复杂度非常easy膨胀,并且会继承父类的全部特性,因为继承为类型引入的静态特质,使得这样的扩展方式缺乏灵活性;同一时候,又掉入了还有一个陷阱,随着扩展功能的增多,子类也会增多,各种子类的组合,就会导致类的膨胀,最后,就会被淹没在类的海洋。

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

decorator(装饰者模式):动态地给一个对象加入一些额外的职责。就添加功能来说,Decorator模式相比生成子类更为灵活。

装饰模式能够实现动态的为对象加入功能,是从一个对象外部来给对象加入功能。通常给对象加入功能,要么直接改动对象加入相应的功能。要么派生相应的子类来扩展。抑或是使用对象组合的方式。

显然。直接改动相应的类这样的方式并不可取。在面向对象的设计中,而我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式。能够非常灵活的给对象加入所须要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。

总之,装饰模式是通过把复杂的功能简单化。分散化。然后再执行期间,依据须要来动态组合的这样一个模式。

它使得我们能够给某个对象而不是整个类加入一些功能。

Component:定义一个对象接口,能够给这些对象动态地加入职责;





ConcreteComponent:定义一个详细的Component。继承自Component,重写了Component类的虚函数。





Decorator:维持一个指向Component对象的指针,该指针指向须要被装饰的对象;并定义一个与Component接口一致的接口。





ConcreteDecorator:向组件加入职责。

使用场景:

1,在不影响其它对象的情况下,以动态的。透明的方式给单个对象加入职责;

2,处理那些能够撤销的职责;

3,当不能採用生成子类的方法进行扩充时。一种情况是。可能存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

还有一种情况可能是由于类定义被隐藏。或类定义不能用于生成子类。

演示样例代码:

#include <iostream>
using namespace std;
class Component
{
public:
virtual void Operation() = 0;
};
class ConcreteComponent : public Component
{
public:
void Operation()
{
cout<<"I am no decoratored ConcreteComponent"<<endl;
}
};
class Decorator : public Component
{
public:
Decorator(Component *pComponent) : m_pComponentObj(pComponent) {}
void Operation()
{
if (m_pComponentObj != NULL)
{
m_pComponentObj->Operation();
}
}
protected:
Component *m_pComponentObj;
};
class ConcreteDecoratorA : public Decorator
{
public:
ConcreteDecoratorA(Component *pDecorator) : Decorator(pDecorator){}
void Operation()
{
AddedBehavior();
Decorator::Operation();
}
void AddedBehavior()
{
cout<<"This is added behavior A."<<endl;
}
};
class ConcreteDecoratorB : public Decorator
{
public:
ConcreteDecoratorB(Component *pDecorator) : Decorator(pDecorator){}
void Operation()
{
AddedBehavior();
Decorator::Operation();
}
void AddedBehavior()
{
cout<<"This is added behavior B."<<endl;
}
};
int main()
{
Component *pComponentObj = new ConcreteComponent();
Decorator *pDecoratorAOjb = new ConcreteDecoratorA(pComponentObj);
pDecoratorAOjb->Operation();
cout<<"============================================="<<endl;
Decorator *pDecoratorBOjb = new ConcreteDecoratorB(pComponentObj);
pDecoratorBOjb->Operation();
cout<<"============================================="<<endl;
Decorator *pDecoratorBAOjb = new ConcreteDecoratorB(pDecoratorAOjb);
pDecoratorBAOjb->Operation();
cout<<"============================================="<<endl;
delete pDecoratorBAOjb;
pDecoratorBAOjb = NULL;
delete pDecoratorBOjb;
pDecoratorBOjb = NULL;
delete pDecoratorAOjb;
pDecoratorAOjb = NULL;
delete pComponentObj;
pComponentObj = NULL;
}

实现要点:

1。接口的一致性;装饰对象的接口必须与它所装饰的Component的接口是一致的。因此,全部的ConcreteDecorator类必须有一个公共的父类。这样对于用户来说,就是统一的接口。

2,省略抽象的Decorator类;当仅须要加入一个职责时,没有必要定义抽象Decorator类。由于我们经常要处理,现存的类层次结构而不是设计一个新系统。这时能够把Decorator向Component转发请求的职责合并到ConcreteDecorator中;

3,保持Component类的简单性;为了保证接口的一致性,组件和装饰必需要有一个公共的Component类,所以保持这个Component类的简单性是很重要的,所以,这个Component类应该集中于定义接口而不是存储数据。

对数据表示的定义应延迟到子类中,否则Component类会变得过于复杂和臃肿。因而难以大量使用。赋予Component类太多的功能。也使得详细的子类有一些它们它们不需要的功能大大增大。

4。Component类在Decorator模式中充当抽象接口的角色,不应该去实现详细的行为。

并且Decorator类对于Component类应该透明,换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。



5,Decorator类在接口上表现为“is-a”Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为“has-a”Component的组合关系。即Decorator类又使用了另外一个Component类。我们能够使用一个或者多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。,

6,Decortor模式并不是解决“多子类衍生的多继承”问题,Decorator模式的应用要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义;

7,对于Decorator模式在实际中的运用能够非常灵活。假设仅仅有一个ConcreteComponent类而没有抽象的Component类。那么Decorator类能够是ConcreteComponent的一个子类。假设仅仅有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而能够把Decorator和ConcreteDecorator的责任合并成一个类。

8,Decorator模式的长处是提供了比继承更加灵活的扩展,通过使用不同的详细装饰类以及这些装饰类的排列组合,能够创造出非常多不同行为的组合。

9,因为使用装饰模式。能够比使用继承关系须要较少数目的类。使用较少的类,当然使设计比較易于进行。可是,在还有一方面。使用装饰模式会产生比使用继承关系很多其它的对象。很多其它的对象会使得查错变得困难,特别是这些对象看上去都非常相像。

[C++设计模式] decorator 装饰者模式的更多相关文章

  1. java设计模式—Decorator装饰者模式

    一.装饰者模式 1.定义及作用 该模式以对客户端透明的方式扩展对象的功能. 2.涉及角色      抽象构件角色:定义一个抽象接口,来规范准备附加功能的类. 具体构件角色:将要被附加功能的类,实现抽象 ...

  2. C#设计模式(9)——装饰者模式(Decorator Pattern)

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

  3. python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

  4. PHP设计模式之装饰器模式(Decorator)

    PHP设计模式之装饰器模式(Decorator) 装饰器模式 装饰器模式允许我们给一个类添加新的功能,而不改变其原有的结构.这种类型的类属于结构类,它是作为现有的类的一个包装 装饰器模式的应用场景 当 ...

  5. java设计模式之七装饰器模式(Decorator)

    顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...

  6. Java 设计模式泛谈&装饰者模式和单例模式

    设计模式(Design Pattern) 1.是一套被反复使用.多人知晓的,经过分类编目 的 代码设计经验总结.使用设计模式是为了可重用代码,让代码更容易维护以及扩展. 2.简单的讲:所谓模式就是得到 ...

  7. 实践GoF的23种设计模式:装饰者模式

    摘要:装饰者模式通过组合的方式,提供了能够动态地给对象/模块扩展新功能的能力.理论上,只要没有限制,它可以一直把功能叠加下去,具有很高的灵活性. 本文分享自华为云社区<[Go实现]实践GoF的2 ...

  8. js原生设计模式——12装饰者模式

    1.面向对象模式装饰者 <!DOCTYPE html><html lang="en"><head>    <meta charset=&q ...

  9. 设计模式之装饰者模式-java实例

    设计模式之装饰者模式 需求场景 我们有了别人提供的产品,但是别人提供的产品对我们来说还不够完善,我们需要对这个产品的功能进行补强,此时可以考虑使用装饰者模式. 我们已经有了产品,而且这个产品的功能非常 ...

随机推荐

  1. WEB前端响应式布局之BootStarp使用

    1.Bootstrap简介:1. 概念: 一个前端开发的框架,Bootstrap,来自 Twitter,是目前很受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JavaScript 的 ...

  2. MFC_2.1使用单选和多选框

    使用单选和多选框 单选 1.拖控件 设置名字,CTRL+D设置顺序,属性设置第一个GROUP为TRUE: 2.设置第一个按钮绑定变量为 值 INT型 名称m_RadioIndxe; 3.设置单击响应内 ...

  3. GEO/SRA数据库

    GEO数据库 GEO数据库隶属于NCBI,是最大最全面的基因表达数据库,主要是芯片和转录组测序数据.除储存数据外,也提供一些数据挖掘工具,因此利用好这个数据库,没有实验,没有自己的数据也能发好文章! ...

  4. API Studio 5.1.2 版本更新:加入全局搜索、支持批量测试API测试用例、读取代码注解生成文档支持Github与码云等

    最近在EOLINKER的开发任务繁重,许久在博客园没有更新产品动态了,经过这些日子,EOLINKER又有了长足的进步,增加了更多易用的功能,比如加入全局搜索.支持批量测试API测试用例.读取代码注解生 ...

  5. Git安装使用指南

    Git安装使用指南 Git原理示意图 1. 安装git Linux服务器版本为Redhat6.2-64,其他版本可能有些许不同 1.1 安装依赖包 在安装git前首先安装依赖包,包括的依赖包有: cv ...

  6. 微信小程序支付全问题解决

    这几天在做小程序的支付,没有用官方的SDK,这里就纯用官方的文档搞一发. * 注作者使用的PHP,不过支付流程都是这样 开发前必读 主要流程 小程序前端发送求参请求 接受请求封装 "统一下单 ...

  7. eclipse自动提示配置

    打开Window->Preferences

  8. 05 Python运算符

    Python运算符: 此图来源于菜鸟教程,更详细参考 http://www.runoob.com/python3/python3-basic-operators.html 说明: 同一优先级的通常从左 ...

  9. vue父组件向子组件传递参数

    父组件中引用的子组件 <pics :is-pics="showpics" // 这是我们要传递的参数 :is-product="productMsg" : ...

  10. 洛谷 1339 [USACO09OCT]热浪Heat Wave

    [题解] 最短路.那么直接写dijkstra就好了. #include<cstdio> #include<algorithm> #include<cstring> ...