引入:
曾今以为继承能解决一切问题。在程序运行时发现,扩展的威力远大于编译时扩展的威力。
装饰者模式:
好处:
一旦知道装饰的技巧,你将能给你的(或别人的)对象一个新的责任,而不需要对底层class的代码做任何改变
p.s. 写代码的时候,尽量少对底层代码做修改。
描述:
装饰者模式动态地将额外责任附加到对象上。
对于扩展功能,装饰者提供子类化之外地弹性替代方案。

设计原则:
类应该对扩展开放,但对修改关闭。
我们的目标是允许类容易扩展以容纳新的行为,而不用修改已有代码。
达成这个目标,有什么好处?
这样的设计可以弹性地应对改变,有足够弹性接纳新的功能来应对改变的需求。

main.cpp

/*** @file main.cpp* @author JeffyGao (gaojune)better@qq.com)* * @version 0.1* @date 2022-04-30* @copyright Copyright (c) 2022* * @brief  本节开始介绍 设计模式03 - 装饰者模式* 文件描述:*  Beverage.h:*      class Beverage      基类                                           (抽象组件)*      class CondimentDecorator : public Beverage 为调料实现抽象类         (抽象装饰者)*  other_Drinks.h:         基于 Beverage (Beverage.h),派生的一些其它饮料*      class Espresso   : public Beverage    浓缩咖啡                      (具体组件)*      class TeaWithMilk : public Beverage   奶茶                          (具体组件)*      *  other_Seasonings.h 基于 CondimentDecorator (Beverage.h),派生的一些其它调料*      class Mocha : public CondimentDecorator 调料 - 摩卡                 (具体装饰者)*      class Cream : public CondimentDecorator 调料 - 奶油                 (具体装饰者)*      class Soy   : public CondimentDecorator 调料 - 豆子                 (具体装饰者)*/#include <iostream>
#include "Other_Drinks.h"
#include "Beverage.h"
#include "Other_Seasonings.h"// 开始下订单
class StabuzzCoffee{public:StabuzzCoffee( ){std::cout << "Begin buy my coffee ctor" << std::endl;}~StabuzzCoffee( ){std::cout << "StabuzzCoffee dtor" << std::endl;}
public:void Print( ){// std::cout << _beverage->GetDescription() << " $ "  << _beverage->Cost() << std::endl;std::cout << _beverage->Cost() << "$" << std::endl;}public:Beverage* _beverage;
};// 点单系统是 一种奶茶/咖啡 + 若干小料
int main( ){std::cout << "No.1" << std::endl;// 来一杯浓缩咖啡,不加调料,打印出它的描述和价格StabuzzCoffee coffee1;coffee1._beverage = new Espresso();std::cout << coffee1._beverage->GetDescription() << std::endl;coffee1.Print();std::cout << "No.2" << std::endl;// 来一杯奶茶(0.89),加 摩卡(0.2)、奶油(0.31)// 在调用 coffee2.Pring() 的时候调用顺序:// -> Cream.Cost() -> Mocha.Cost() -> TraWithMilk.Cost() StabuzzCoffee coffee2;coffee2._beverage = new TeaWithMilk();coffee2._beverage = new Mocha( coffee2._beverage );coffee2._beverage = new Cream( coffee2._beverage );std::cout << coffee2._beverage->GetDescription() << std::endl;coffee2.Print();return 0;
}

Beverage.h

/*** @file Beverage.h* @author JeffyGao (gaojune)better@qq.com) * @version 0.1* @date 2022-04-30* @copyright Copyright (c) 2022* * @brief 这是一个抽象类 的基类* * 文件包含:*      GetDescription() 商品描述*      virtual double Cost() = 0 商品花费*      * */#ifndef BEVERAGE_H
#define BEVERAGE_H#include <iostream>
#include <string.h>class Beverage{public:Beverage( ){std::cout << "Beverage ctor" << std::endl;}// 要定义 虚函数virtual ~Beverage( ){std::cout << "Beverage dtor" << std::endl;}public:// 公共接口// 商品描述virtual std::string GetDescription( ){return _description;}// 商品花费// 这里不能定义为 纯虚函数,不然 class CondimentDecorator 无法实例化_beveragevirtual double Cost( ) = 0;//virtual double Cost( ) {}     // 如果要定义为虚函数的话要定义 {}// double Cost( ){//     std::cout << " Beverage Cost()" << std::endl;//     return (double)12345.1234;// }// 不能设置为 private,不然派生类无法更改改变量std::string _description = "Unknown Beverage  ";};// 为调料实现抽象类
class CondimentDecorator : public Beverage{public:CondimentDecorator( ){std::cout << "CondimentDecorator ctor" << std::endl;}~CondimentDecorator( ){std::cout << "CondimentDecorator dtor" << std::endl;}public:// 书中这一行没看懂 =>  在 Other_Seasonings.h 中要实例化// 我在 Beverage 中将 Cost( ) 定义了纯虚函数,因此不能直接实例化,只能实例化其指针// 要想能实例化其对象的话,另一种方法是定义好其虚构函数{}Beverage* _beverage;// 重写 GetDescription()virtual std::string GetDescription( ) {return _description;}};#endif

Other_Drinks.h

/*** @file Other_dring.h* @author effyGao (gaojune)better@qq.com)* @version 0.1* @date 2022-04-30* @copyright Copyright (c) 2022* * @brief 基于 基类 Beverage (Beverage.h),派生的一些其它饮料* * 文件包含:*  class Espresso : public Beverage ,浓缩咖啡*      Espresso()      更改 _description*      Cost()          重写了 Cost()*  class TeaWithMilk : public Beverage, 奶茶*      TeaWithMilk()   更改 _description*      Cost()          重写了 Cost()*/#ifndef OTHER_DRINKS_H
#define OTHER_DRINKS_H#include "Beverage.h"
#include <iostream>// 浓缩咖啡 (具体组件)
class Espresso : public Beverage{public:Espresso( ){//std::cout << "Espresso ctor" << std::endl;_description= "订单详情: 浓缩咖啡 ";   // 并更改描述}~Espresso( ){std::cout << "Espresso dtor" << std::endl;}public:// 重写了 Cost()double Cost( ){std::cout << "共花费:  ";return 1.99;}
};// 奶茶    (具体组件)
class TeaWithMilk : public Beverage{public:TeaWithMilk( ){//std::cout << "TeaWithMilk ctor" << std::endl;_description= "订单详情: 奶茶 ";   // 并更改描述}~TeaWithMilk( ){std::cout << "TeaWithMilk dtor" << std::endl;}public:// 重写了 Cost()double Cost( ){std::cout << "共花费:    ";return 0.89;}
};#endif

Other_Seaonings.h

/*** @file Other_Seasonings.h* @author effyGao (gaojune)better@qq.com)* @version 0.1* @date 2022-04-30* @copyright Copyright (c) 2022* * @brief   一些调料~ *  基于 基类 CondimentDecorator (Beverage.h),派生的一些其它调料* * 文件包含:*  class Mocha : public CondimentDecorator 调料 - 摩卡 (具体装饰者)*  class Cream : public CondimentDecorator 调料 - 奶油 (具体装饰者)*  class Soy   : public CondimentDecorator 调料 - 豆子 (具体装饰者)* *  // 构造函数 传入 Beverage* 型, 在 main.cpp 中通过包裹对象来实现“加小料”,反馈相应的Cost()*/#ifndef OTHER_SEASONINGS_H
#define OTHER_SEASONINGS_H#include <iostream>
#include "Beverage.h"
#include <string>// 调料 - 摩卡 具体装饰着
class Mocha : public CondimentDecorator{public:Mocha( ){std::cout << "Mocha ctor" << std::endl;}Mocha( Beverage* beverage ){std::cout << "Mocha( Beverage beverage )" << std::endl;// 在这里实例变量为正在包裹的对象。// 这里,我们可以传递正在包装的饮料给装饰者的构造器。this->_beverage = beverage;}~Mocha( ){std::cout << "Mocha dtor" << std::endl;}public:// 重写方法// 饮料 Description + Mocha 描述std::string GetDescription( ){std::string name = _beverage->GetDescription() + " , Mocha";return  name;}// 饮料 Cost +  Mocha 价格double Cost( ){return _beverage->Cost() + 0.20;}
};// 调料 - 奶油 具体装饰着
class Cream : public CondimentDecorator{public:Cream( ){std::cout << "Cream ctor" << std::endl;}Cream( Beverage* beverage ){std::cout << "Cream( Beverage beverage )" << std::endl;// 在这里实例变量为正在包裹的对象。// 这里,我们可以传递正在包装的饮料给装饰者的构造器。this->_beverage = beverage;}~Cream( ){std::cout << "Cream dtor" << std::endl;}public:// 重写方法// 饮料 Description + Cream 描述std::string GetDescription( ){//std::cout << "调用了 奶油" << std::endl;std::string name = _beverage->GetDescription() + " , Cream";return  name;}// 饮料 Cost +  Cream 价格double Cost( ){return _beverage->Cost() + 0.31;}
};// 调料 - 豆子 具体装饰着
class Soy : public CondimentDecorator{public:Soy( ){std::cout << "Soy ctor" << std::endl;}Soy( Beverage* beverage ){std::cout << "Soy( Beverage beverage )" << std::endl;// 在这里实例变量为正在包裹的对象。// 这里,我们可以传递正在包装的饮料给装饰者的构造器。this->_beverage = beverage;}~Soy( ){std::cout << "Soy dtor" << std::endl;}public:// 重写方法// 饮料 Description + Soy 描述std::string GetDescription( ){std::string name = _beverage->GetDescription() + " , Soy";return  name;}// 饮料 Cost +  Soy 价格double Cost( ){return _beverage->Cost() + 0.39;}
};#endif  

设计模式03 - 装饰者模式相关推荐

  1. Java设计模式(装饰者模式-组合模式-外观模式-享元模式)

    Java设计模式Ⅳ 1.装饰者模式 1.1 装饰者模式概述 1.2 代码理解 2.组合模式 2.1 组合模式概述 2.2 代码理解 3.外观模式 3.1 外观模式概述 3.2 代码理解 4.享元模式 ...

  2. 前端也要学系列:设计模式之装饰者模式

    什么是装饰者模式 今天我们来讲另外一个非常实用的设计模式:装饰者模式.这个名字听上去有些莫名其妙,不着急,我们先来记住它的一个别名:包装器模式. 我们记着这两个名字来开始今天的文章. 首先还是上< ...

  3. 设计模式 之 装饰者模式

    2019独角兽企业重金招聘Python工程师标准>>> 设计模式 之 装饰者模式 装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对 ...

  4. 【设计模式】装饰者模式 ( 概念 | 适用场景 | 优缺点 | 与继承对比 | 定义流程 | 运行机制 | 案例分析 )

    文章目录 I . 装饰者模式概念 II . 装饰者模式适用场景 III . 装饰者模式优缺点 IV . 装饰者模式与继承对比 V . 装饰者模式相关设计模式 VI . 装饰者模式四个相关类 VII . ...

  5. 设计模式学习----装饰器模式

    这两天本来是自在学习java collection Framework的Fail Fast底层机制,看到核心的部分时,突然意识到设计模式的问题,上大学到现在我还没有真正理解过设计模式的概念,于是用了大 ...

  6. 【设计模式】装饰器模式的使用

    问题来源 我们在进行软件系统设计的时候,有一些业务(如下图,一些通用的非功能性需求)是多个模块都需要的,是跨越模块的.把它们放到什么地方呢? 最简单的办法就是把这些通用模块的接口写好,让程序员在实现业 ...

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

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

  8. go设计模式之装饰器模式

    go设计模式之装饰器模式 再写这篇文章时,我已经看了很多其他人发表的类似文章,大概看了这么多吧. 亓斌的设计模式-装饰者模式(Go语言描述) jeanphorn的Golang设计模式之装饰模式 七八月 ...

  9. python中的装饰器、装饰器模式_python 设计模式之装饰器模式 Decorator Pattern

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

最新文章

  1. 深度学习目标检测(object detection)系列(一) R-CNN
  2. 解决TensorBoard训练集和测试集指标只能分开显示的问题(基于Keras)
  3. java spring 服务器关闭_通过springboot怎么停止服务器??
  4. android圆形进度条ProgressBar颜色设置
  5. 基本排序算法之4——归并排序mergesort
  6. 使用Eclipse连接SAP云平台上的HANA数据库实例
  7. opencv 最大连通域_opencv 查找连通区域 最大面积实例
  8. jzoj3853-帮助Bsny【dp】
  9. 详解异构计算FPGA基础知识
  10. php scope权限管理,关于微信公众号scope参数错误或没有scope权限的解决方案
  11. 【渗透测试实战】PHP语言有哪些后门?以及利用方法
  12. 初级程序员面试不靠谱指南(二)
  13. java从入门到入土_java从入门到入土---基础篇04---IO
  14. Hadoop配置文件( hadoop-env.sh、core-site.xml、hdfs-site.xm、mapred-site.xml、yarn-site.xml、 slaves)详解
  15. java进制转换方法
  16. 日更第17天:Linux常用命令之ps用法
  17. 电商基本功:被小瞧的促销设计,并没有想得那么简单
  18. 智能运维 | 我们不一样!告诉你百度云如何做智能流量异常检测
  19. Java实现HighCharts纯后台图表生成
  20. 性能测试方案与性能测试报告目录导航

热门文章

  1. 基于C#实现的在线聊天室的桌面系统软件
  2. 专升本——非谓语动词
  3. 【数学建模】“一口价”的战略(博弈模型)
  4. 计算机体系架构(1)计算机组成原理
  5. 提问的艺术 | 如何聪明地提问
  6. 数据库的视图,视图的更新,视图的可操作性
  7. java web 开发是做什么用的?
  8. python单词词典_Python自然语言处理学习笔记(42):5.3 使用Python字典将单词映射到属性...
  9. 基于ESP32的SPI读取MPU9250数据
  10. windows 如何查看、修改MAC地址?