设计模式——装饰模式

news2025/2/14 0:16:29

文章目录

  • 1.定义
  • 2. 结构组成
  • 3. 组合模式结构
  • 4. 示例代码
  • 5. 模式优势
  • 6. 应用场景

1.定义

装饰模式就像是给你的对象穿上不同的 “时尚服装”,在程序运行时,你可以随意地给对象搭配各种 “服装” 来增加新的功能,而且完全不用对对象本身的 “身材”(类结构)进行修改。这是一种很巧妙的设计模式,能够让对象在不改变自身本质的情况下,变得更加 “华丽”。

2. 结构组成

  • Component(组件):
    • 这就好比是一个标准的 “衣架”,它定义了所有可以被装饰的对象的基本 “穿搭风格”(行为)。在装饰模式里,这个 “衣架” 接口有一个 “execute ()” 方法,这就像是所有衣服(具体组件和装饰器)都要能挂在这个衣架上的基本要求。
  • Concrete Component(具体组件):
    • 这是一件最基础的 “衣服”,它按照 “衣架”(Component)的标准制作出来,提供了最基础的 “穿搭效果”(实现了 “execute ()” 方法),代表了对象最原始的功能。
  • Base Decorator(基础装饰器):
    • 这是一个特别的 “衣架外套”,它本身也是按照 “衣架” 的标准制作的(实现了 Component 接口)。它里面还藏着一个对其他 “衣服”(Component 对象)的引用,当你穿上这个 “衣架外套” 时,它会把里面的 “衣服” 也展示出来(在其 “execute ()” 方法中调用 “wrappee” 的 “execute ()” 方法)。
  • Concrete Decorators(具体装饰器):
    • 这些就像是各种各样的 “时尚配饰”,它们都继承自 “衣架外套”(Base Decorator)。当你把这些 “配饰” 挂在 “衣架” 上时,它们可以在展示里面 “衣服”(调用被装饰对象的方法)的前后,添加一些额外的 “时尚元素”(额外的行为)。

3. 组合模式结构

在这里插入图片描述

  • 创建基础对象:就像你要开始搭配穿搭一样,首先你有了一件基础的 “衣服”(客户端创建一个具体组件对象,例如a = new ConcComponent()),这是最基础的穿搭风格。
  • 添加装饰器:接着,你可以给这件基础 “衣服” 搭配上一件 “衣架外套”,比如 “时尚配饰 1”(b = new ConcDecorator1(a),这里 “ConcDecorator1” 是一个具体装饰器,它包装了基础对象 “a”)。
    你还可以继续在外面添加更多的 “时尚配饰”,像 “时尚配饰 2”(c = new ConcDecorator2(b),这里 “ConcDecorator2” 又包装了 “b”,形成了一个装饰器链),让你的穿搭变得更加独特。
  • 执行操作: 最后,当你穿上这套精心搭配的 “衣服”(调用最外层装饰器的 “execute ()” 方法,如c.execute())时,会按照从外到内的顺序展示出每一件 “衣服” 和 “配饰” 的效果:
    • 首先,“时尚配饰 2”(“ConcDecorator2”)会展示它的 “时尚元素”,它可能会在展示里面 “衣服”(调用被装饰对象 “b” 的方法)之前或之后添加一些独特的风格。
    • 然后,“时尚配饰 1”(“ConcDecorator1”)也会展示它的特色,同样可能添加额外的时尚效果。
    • 最后,基础的 “衣服”(“a”)的效果会被展示出来,完成整个 “时尚穿搭秀”(操作)。

4. 示例代码


#include <iostream>
#include <memory>

using namespace std;

class Component{
public:
    Component(){cout << "Component Constructor " <<endl;}   
    virtual ~Component(){cout << "Component Destructor " <<endl;}   
    virtual string Operation() const = 0;
};

class ConcreteComponent : public Component{
public:
    ConcreteComponent(){cout << "ConcreteComponent Constructor " <<endl;}   
    ~ConcreteComponent(){cout << "ConcreteComponent Destructor " <<endl;}
    
    string Operation() const override{
        return "ConcreteComponent";
    }
};

class Decorator : public Component{
protected:
    shared_ptr<Component> component_;
public:
    Decorator(shared_ptr<Component> component) : component_ (component){
        cout << "Decorator Constructor " <<endl;
    }   
    ~Decorator(){cout << "Decorator Destructor " <<endl;}
    
    string Operation() const override{
        return component_->Operation();
    }
};

class ConcreteDecoratorA : public Decorator{
public:
    ConcreteDecoratorA(shared_ptr<Component> component) : Decorator (component){
        cout << "ConcreteDecoratorA Constructor " <<endl;
    }   
    ~ConcreteDecoratorA(){cout << "ConcreteDecoratorA Destructor " <<endl;}
    
    string Operation() const override{
        return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
    }
};

class ConcreteDecoratorB : public Decorator{
public:
    ConcreteDecoratorB(shared_ptr<Component> component) : Decorator(component){
        cout << "ConcreteDecoratorB Constructor " <<endl;
    }   
    ~ConcreteDecoratorB(){cout << "ConcreteDecoratorB Destructor " <<endl;}
    
    string Operation() const override{
        return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
    }
};

void ClientCode(shared_ptr<Component> component){
    cout<< component->Operation() <<endl;
}

int main()
{
    shared_ptr<Component> simple = make_shared<ConcreteComponent>();
    cout << "Client: I've got a simple component:\n";
    ClientCode(simple);
    cout << "\n\n";
    
    shared_ptr<Component> decorator1 = make_shared<ConcreteDecoratorA>(simple);
    shared_ptr<Component> decorator2 = make_shared<ConcreteDecoratorB>(decorator1);
    cout << "Client: Now I've got a decorated component:\n";
    ClientCode(decorator2);
    std::cout << "\n";
   
    return 0;
}

5. 模式优势

  • 灵活性高
    • 这种模式就像你的时尚穿搭可以随时变化一样,在程序运行时,你可以动态地给对象添加或移除各种 “时尚元素”(功能),完全不用改变对象本身的 “身材”(结构)。比如,你可以根据当天的心情或者场合,随意地给对象搭配不同的功能。
  • 可扩展性好
    • 当你想要一种新的 “时尚风格”(功能)时,只需要轻松地设计一个新的 “时尚配饰”(装饰器)就可以了,完全符合程序设计中的 “开闭原则”。这就好比你想要一种新的穿搭风格,只需要买一个新的配饰,而不用重新设计一件衣服。
  • 复用性强
    • 无论是基础的 “衣服”(组件)还是各种 “时尚配饰”(装饰器),都可以被重复使用,大大减少了代码的重复。就像你可以用同一件基础衣服搭配不同的配饰,或者把同一个配饰用在不同的穿搭上。

6. 应用场景

  • 动态添加功能
    • 当你在程序中需要像在穿搭中根据心情或场合动态地给对象添加新功能时,装饰模式就非常有用了。例如,在图形用户界面(GUI)中,你可以像给窗口搭配不同的 “时尚元素” 一样,给窗口添加边框、滚动条等装饰。
  • 避免类爆炸
    • 当你发现如果用传统的继承方式来给对象添加功能,会导致像衣柜里堆满了各种相似但又略有不同的衣服一样(类爆炸),装饰模式就可以通过像搭配穿搭一样的组合方式来替代继承,更加灵活地扩展功能。
  • 多特性组合
    • 当你有很多像时尚配饰一样的特性需要组合到一个对象上,而且这些特性可以像穿搭一样动态地添加或移除时,装饰模式就派上用场了。比如在咖啡制作系统中,咖啡就像基础的衣服,而糖、奶、巧克力等配料就像各种时尚配饰,每种配料都可以看作是一个装饰器,你可以根据自己的口味随意搭配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2266075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python+reportlab创建PDF文件

目录 字体导入 画布写入 创建画布对象 写入文本内容 写入图片内容 新增页 画线 表格 保存 模板写入 创建模板对象 段落及样式 表格及样式 画框 图片 页眉页脚 添加图形 构建pdf文件 reportlab库支持创建包含文本、图像、图形和表格的复杂PDF文档。 安装&…

<数据集>芝麻作物和杂草识别数据集<目标检测>

数据集下载链接 &#xff1c;数据集&#xff1e;芝麻作物和杂草识别数据集&#xff1c;目标检测&#xff1e;https://download.csdn.net/download/qq_53332949/90181548数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1300张 标注数量(xml文件个数)&#xff1a;130…

Python爬虫:速卖通aliexpress商品详情获取指南

在数字化时代&#xff0c;数据已成为企业竞争的关键资源。对于电商行业而言&#xff0c;获取竞争对手的商品信息是洞察市场动态、优化自身产品策略的重要手段。速卖通&#xff08;AliExpress&#xff09;作为全球知名的跨境电商平台&#xff0c;其商品信息的获取自然成为了许多…

【绿色碳中和】全国各省各地级市绿色金融数据(1990-2022年)

数据介绍&#xff1a;绿色金融指数采用熵值法进行测算&#xff0c;综合评价体系如下&#xff1a; 绿色金融指标体系 二级指标 三级指标 指标说明 绿色信贷 高能耗行业利息支出占比 六大高能耗行业利息支出/工业总利息 A股上市公司环保企业新增银行贷款占比 …

React引入Echart水球图

在搭建React项目时候&#xff0c;遇到了Echart官方文档中没有的水球图&#xff0c;此时该如何配置并将它显示到项目中呢&#xff1f; 目录 一、拓展网站 二、安装 三、React中引入 1、在components文件夹下新建一个组件 2、在组件中引入 3、使用水波球组件 一、拓展网站 …

Vue使用Tinymce 编辑器

目录 一、下载并重新组织tinymce结构二、使用三、遇到的坑 一、下载并重新组织tinymce结构 下载 npm install tinymce^7 or yarn add tinymce^7重构目录 在node_moudles里找到tinymce文件夹&#xff0c;把里面文件拷贝一份放到public下&#xff0c;如下&#xff1a; -- pub…

STM32-笔记10-手写延时函数(SysTick)

1、什么是SysTick Systick&#xff0c;即滴答定时器&#xff0c;是内核中的一个特殊定时器&#xff0c;用于提供系统级的定时服务。该定时器是一个24位的倒计数定时器‌。它从设定的初值&#xff08;即重载值&#xff09;开始计数&#xff0c;每经过一个系统时钟周期&#xff0…

Elasticsearch-脚本查询

脚本查询 概念 Scripting是Elasticsearch支持的一种专门用于复杂场景下支持自定义编程的强大的脚本功能&#xff0c;ES支持多种脚本语言&#xff0c;如painless&#xff0c;其语法类似于Java,也有注释、关键字、类型、变量、函数等&#xff0c;其就要相对于其他脚本高出几倍的性…

C项目 天天酷跑(下篇)

上篇再博客里面有&#xff0c;接下来我们实现我们剩下要实现的功能 文章目录 碰撞检测 血条的实现 积分计数器 前言 我们现在要继续优化我们的程序才可以使这个程序更加的全面 碰撞的检测 定义全局变量 实现全局变量 void checkHit() {for (int i 0; i < OBSTACLE_C…

设计模式详解(建造者模式)

1、简述 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它通过将对象的构造过程与表示分离&#xff0c;使得相同的构造过程可以创建不同的表示。建造者模式尤其适用于创建复杂对象的场景。 2、什么是建造者模式&#xff1f; 建造者模式…

【Git 常用操作:pull push】

Git 基本概念 Git 是一个先进的开源的分布式版本控制系统&#xff0c;常用于管理工作内容、项目代码等功能。 Git 工作流程 图片来源&#xff1a;https://www.runoob.com/git/git-basic-operations.html 说明&#xff1a; workspace&#xff1a;工作区staging area&#xff…

个人笔记:ORM数据库框架EFCore使用示例,运行通过,附源码

个人笔记&#xff1a;ORM数据库框架EFCore使用示例&#xff0c;运行通过&#xff0c;附源码 0.新建项目1. 设置环境1.1. 添加 NuGet 包1.2. 创建模型类 2. 创建上下文类3. 创建数据库和表3.1. 启用迁移3.2. 更新数据库 4. 插入数据5. 查询数据6. 更新数据7. 删除数据8. 完整示例…

IndexOf Apache Web For Liunx索引服务器部署及应用

Apache HTTP Server 是一款广泛使用的开源网页服务器软件,它支持多种协议,包括 HTTP、HTTPS、FTP 等 IndexOf 功能通常指的是在一个目录中自动生成一个索引页面的能力,这个页面会列出该目录下所有的文件和子目录。比如网上经常看到的下图展现的效果,那么接下来我们就讲一下…

Ubuntu 24.04.1 LTS快速源码安装postgresql15

虽然在Ubuntu中我们可以通过apt直接获取postgresql安装&#xff0c;但有些时候&#xff0c;为了自行配置postgresql安装路径和部分组件参数&#xff0c;我们需要源码安装postgresql。今天我们就通过源码编译postgresql15源码进行安装。 一、获取安装包 我们登录postgresql官网…

数据结构之栈,队列,树

目录 一.栈 1.栈的概念及结构 2.栈的实现 3.实现讲解 1.初始化栈 2.销毁栈 3.压栈 4.出栈 5.返回栈顶元素 6.返回栈内元素个数 7.判断栈内是否为空 二.队列 1.队列的概念及结构 2.队列的实现 3.实现讲解 1.初始化队列 2.销毁队列 3.单个成员入队列 4.单个成员…

Git基本操作快速入门(30min)

Git基本操作快速入门&#xff08;30min&#xff09; 文章目录 Git基本操作快速入门&#xff08;30min&#xff09;1. 建立本地仓库2. 本地仓库链接到远端仓库3. 将本地仓库推送到远端4. Git常用命令 作为一名程序员&#xff0c;使用Github来进行代码的版本管理是必修课&#xf…

汽车IVI中控开发入门及进阶(42):OpenVG

概览: OpenVG是一个无版权、跨平台的API,它为高级用户界面和矢量图形库(如SVG)提供了一个低级硬件加速接口。OpenVG主要针对需要便携式加速高质量矢量图形以获得引人注目的用户界面和文本的消费电子产品、手持设备、可穿戴设备和汽车设备,同时使硬件加速能够在非常低的功…

[1111].集成开发工具Pycharm安装与使用

所有博客大纲 后端学习大纲 Python大纲 1.下载&#xff1a; 官方下载地址 2.安装&#xff1a; 1.双击exe文件&#xff0c;然后下一步选择安装目录 2.选择桌面快捷方式及安装&#xff1a; 3.安装完成 3.启动&#xff1a; 4.设置&#xff1a; 4.1.设置运行时环境&#xff1a;…

Windows11 安装 Ubuntu-20.04,同时安装配置 zsh shell,配置 git 别名(alias),大大提高开发效率

背景&#xff1a;家里配置了一台 Windows 电脑&#xff0c;有时候需要用到 vscode 开发测试一些代码&#xff0c;在使用过程中发现原生 windows 敲代码不是很友好&#xff0c;于是想到配置 wsl&#xff0c;安装 Ubuntu&#xff0c;并安装配置 zsh shell&#xff0c;同时配置 gi…

面试场景题系列:设计限流器

首先看看使用API限流器的好处。 •预防由拒绝服务攻击(Denial of Service&#xff0c;DoS)引起的资源耗尽问题。大型科技公司发布的所有API几乎都强制执行某种形式的限流操作。例如&#xff0c;推特限制每个用户每3小时最多发300条推文。谷歌文档API的默认限制是每个用户每60秒…