当前位置: 首页 > news >正文

设计模式之装饰设计模式

一、装饰设计模式概念

装饰模式 (Decorator) 是一种结构型设计模式,动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。

  • 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
  • 装饰对象包含一个真实对象的引用(reference)。
  • 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
  • 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

 适用场景

  • 如果你希望在无需修改代码的情况下即可使用对象, 且希望在运行时为对象新增额外的行为, 可以使用装饰模式。
  • 如果用继承来扩展对象行为的方案难以实现或者根本不可行, 你可以使用该模式。

组合设计模式的结构

  1. 部件 (Component) 声明封装器和被封装对象的公用接口。
  2. 具体部件 (Concrete Component) 类是被封装对象所属的类。 它定义了基础行为, 但装饰类可以改变这些行为。
  3. 基础装饰 (Base Decorator) 类拥有一个指向被封装对象的引用成员变量。 该变量的类型应当被声明为通用部件接口, 这样它就可以引用具体的部件和装饰。 装饰基类会将所有操作委派给被封装的对象。
  4. 具体装饰类 (Concrete Decorators) 定义了可动态添加到部件的额外行为。 具体装饰类会重写装饰基类的方法, 并在调用父类方法之前或之后进行额外的行为。
  5. 客户端 (Client) 可以使用多层装饰来封装部件, 只要它能使用通用接口与所有对象互动即可。

代码如下:

问题:饮料店订单系统,饮料有咖啡、奶茶、果汁,饮料可以加糖、加奶、加冰。


解决方案:动态的给饮料添加新的功能,而不需要修改饮料的代码。就增加功能来说,装饰模式比继承更加灵活。找出基本组件和可选层次。

#include<iostream>
#include<string>
//接口:具体被包裹的类,以及装饰类
class Beverage
{
public:virtual ~Beverage() {}virtual std::string Operation()const = 0;};
//具体类:被装饰的类
class Americano :public Beverage
{
public:~Americano() {}std::string Operation()const{return "Americano";}
};
//装饰类:给被装饰的类添加新的功能
//基础部分(可能包括额外部分)
class Ingredient :public Beverage
{
protected:Beverage* m_beverage;
public:~Ingredient() {}Ingredient(Beverage* beverage) :m_beverage(beverage) {}std::string Operation()const override{return m_beverage->Operation();//核心代码,不是用来被基类覆盖的}
};
//额外部分(需要委托基类,完成基础部分)
class Whip : public Ingredient
{
public:~Whip() {}Whip(Beverage* beverage):Ingredient(beverage) {}std::string Operation()const override{//在基类的operation之前,之后都可以增加额外的操作return "(奶昔" + m_beverage->Operation() + ")";}
};class Mocha : public Ingredient
{
public:~Mocha() {}Mocha(Beverage* beverage) :Ingredient(beverage) {}std::string Operation()const override{//在基类的operation之前,之后都可以增加额外的操作return "(摩卡" + m_beverage->Operation() + ")";}
};
void ClientCode(Beverage* beverage)
{std::cout<<"执行结果:"<<beverage->Operation()<<std::endl;
}int main()
{Beverage* americano = new Americano();ClientCode(americano);std::cout << "添加2摩卡+奶昔" << std::endl;Beverage* whip = new Whip(americano);Beverage* mocha1 = new Mocha(whip);Beverage* mocha2 = new Mocha(mocha1);ClientCode(mocha2);delete mocha2;delete mocha1;delete whip;delete americano;return 0;
}

http://www.mrgr.cn/news/24928.html

相关文章:

  • 城市道路街景的绿视率计算 绿化率计算(包括街景的获取)
  • 非线性规划及其MATLAB实现
  • 021.PL-SQL控制结构
  • 嵌入式硬件基础知识
  • Centos7.9下的snmp搭建及实例
  • 第 7 篇 Helm 部署 Nacos【详细步骤】
  • Java控制台+activiti+springboot+mybatis实现账务报销工作流程
  • 华为OD机试 - 周末爬山 - 广度优先搜索BFS(Python/JS/C/C++ 2024 E卷 200分)
  • 通用与专用LabVIEW软件版本对比
  • MAX3483ESA+T具有±15kV ESD保护的+3.3V、低功耗收发器,适用于RS-485和RS-422通信
  • 【时时三省】tessy 单元测试 集成测试 专栏 文章阅读说明
  • C#里的分治算法和汉诺塔问题
  • 可解释性机器学习的目标
  • c语言位运算符速成
  • SciPy 模块列表
  • 如何删除电脑系统桌面文件右键菜单多余选项
  • 用Blender来烘培模型材质
  • 赋能百业:多模态处理技术与大模型架构下的AI解决方案落地实践
  • 如何在 Ubuntu 系统上部署 Laravel 项目 ?
  • Java 每日一刊(第4期):Java 23 即将发布