2023-6-26-第八式装饰器模式

news2024/11/18 13:36:45


🍿*★,°*:.☆( ̄▽ ̄)/$:*.°★* 🍿

💥💥💥欢迎来到🤞汤姆🤞的csdn博文💥💥💥
💟💟喜欢的朋友可以关注一下,下次更新不迷路💟💟
😆😆😆私聊获取个人订阅号哦,欢迎订阅共同学习😆😆😆
💖💖💖💖可以加入大家庭群聊,一起学习天天有福利💖💖💖💖





🍬本文摘要

在这里插入图片描述

设计方法二十三式之装饰器模式


目录

  • 🍬本文摘要
  • 😉一、基础概念
  • 🐱‍🐉二、装饰器模式实现
  • 🎉三、模块之间的关系
  • 🐱‍🚀四、注意事项
  • 🎂五、使用场景
  • 🍳参考文献
  • 🧊文章总结



😉一、基础概念

装饰器模式是一种结构型设计模式,它通过动态的将责任附加到对象上来扩展对象的功能。换句话说,它提供了一种不通过子类化就能扩展对象功能的方式。装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。

在装饰器模式中,有一个基本的对象,称之为组件(component),它定义了一个共同的接口,可以被具体的组件或装饰器所实现。装饰器(decorator)会对组件进行包装,从而给组件增加新的功能。装饰器也实现了组件的接口,所以它们可以互相嵌套和组合,从而形成一个功能更加丰富的对象。

在代码实现上,装饰器模式使用一个装饰器类对组件进行包装,并将其传递给另一个装饰器,直到所有的装饰器都被执行完毕。这个过程中,每个装饰器都可以通过调用组件的方法来增加、修改或删除组件的行为。最终,得到的对象拥有了所有的装饰器所提供的功能。

所以,装饰器模式的优点在于:可以动态地给对象增加新的功能,而不需要修改原有的代码。缺点在于:装饰器的嵌套可能会导致复杂的代码结构,而且不正确地使用装饰器将使代码难以维护。


🐱‍🐉二、装饰器模式实现

首先,我们定义一个基础组件类Component和一个具体组件类ConcreteComponent:

class Component {
public:
    virtual void operation() = 0;
};

class ConcreteComponent : public Component {
public:
    virtual void operation() override {
        std::cout << "ConcreteComponent operation.\n";
    }
};

然后我们定义一个装饰器类Decorator,它继承自Component并持有一个指向Component对象的指针,以便在装饰过程中调用原对象的方法。Decorator还定义了一个名为addBehavior()的纯虚函数,用于在装饰过程中添加新功能。

class Decorator : public Component {
public:
    Decorator(Component* component) : component_(component) {}
    virtual void operation() override {
        if (component_)
            component_->operation();
    }
    virtual void addBehavior() = 0;
protected:
    Component* component_;
};

接下来,我们定义两个具体装饰器类ConcreteDecoratorA和ConcreteDecoratorB,它们继承自Decorator并重写了operation()和addBehavior()方法,以实现自定义的装饰功能。

class ConcreteDecoratorA : public Decorator {
public:
    ConcreteDecoratorA(Component* component) : Decorator(component) {}
    virtual void operation() override {
        Decorator::operation();
        std::cout << "ConcreteDecoratorA operation.\n";
    }
    virtual void addBehavior() override {
        std::cout << "ConcreteDecoratorA added behavior.\n";
    }
};

class ConcreteDecoratorB : public Decorator {
public:
    ConcreteDecoratorB(Component* component) : Decorator(component) {}
    virtual void operation() override {
        Decorator::operation();
        std::cout << "ConcreteDecoratorB operation.\n";
    }
    virtual void addBehavior() override {
        std::cout << "ConcreteDecoratorB added behavior.\n";
    }
};

最后,我们可以在客户端代码中使用这些类来实现装饰器模式。我们首先创建一个具体组件对象ConcreteComponent,然后将其传递给ConcreteDecoratorA对象,并调用addBehavior()方法来添加新功能。随后,我们将ConcreteDecoratorA对象传递给ConcreteDecoratorB对象再次添加新功能,并调用operation()方法,输出所有添加的功能。

int main() {
    Component* component = new ConcreteComponent();
    ConcreteDecoratorA* decoratorA = new ConcreteDecoratorA(component);
    decoratorA->addBehavior();
    ConcreteDecoratorB* decoratorB = new ConcreteDecoratorB(decoratorA);
    decoratorB->addBehavior();
    decoratorB->operation();

    delete decoratorB;
    delete decoratorA;
    delete component;
    return 0;
}

输出结果如下:

ConcreteComponent operation.
ConcreteDecoratorA operation.
ConcreteDecoratorA added behavior.
ConcreteDecoratorB operation.
ConcreteDecoratorB added behavior.

🎉三、模块之间的关系

在装饰器模式中,有四个关键角色:抽象组件、具体组件、抽象装饰器和具体装饰器。

抽象组件是定义对象的接口,可以是抽象类或接口,具体组件是实现抽象组件的类,具体装饰器是实现抽象装饰器的类,抽象装饰器是定义装饰器的接口,可以是抽象类或接口。

这四个角色之间的关系是:抽象组件可以包含具体组件,抽象装饰器可以包含抽象组件,具体装饰器可以包含抽象装饰器,具体装饰器也可以包含具体组件,形成一个以抽象装饰器为根节点的装饰器链。通过这个链,每一个装饰器都可以动态地为组件添加新的功能。

当客户端想要使用某个具体组件时,可以使用抽象装饰器来对其进行装饰,不需要知道具体组件的实现细节,这样可以实现组件与装饰器的解耦。


🐱‍🚀四、注意事项

使用桥接模式时需要注意以下事项:

  1. 抽象部分与实现部分分离。在使用桥接模式时,需要将抽象部分与实现部分分离开来,确保它们可以独立进行变化。这有助于提高系统的灵活性和可扩展性。

  2. 接口细化。在设计抽象部分和实现部分的接口时,需要尽可能细化,以确保它们的功能可以清晰地描述。

  3. 优先使用对象组合。在实现桥接模式时,需要优先使用对象组合,而不是继承。如果使用继承,可能会引发类层次结构的剧增,导致系统难以维护。

  4. 不要滥用桥接模式。桥接模式并不是一种万能模式,使用时需要根据具体情况来决定是否使用。如果使用不当,可能会导致系统的复杂度增加,反而降低系统的可维护性和可扩展性。

  5. 安全性考虑。在使用桥接模式时,需要考虑安全性的问题。特别是在桥接的两端,需要确保数据的完整性和安全性。


🎂五、使用场景

桥接模式适用于以下场景:

1.抽象和实现部分具有平行的等级结构,需要在运行时动态组合它们。桥接模式能够使抽象和实现部分各自独立变化,且能够在运行时动态组合它们,因此能够很好地适应这种场景。

2.要求不同的抽象子类可以与不同的实现子类进行组合。桥接模式能够通过抽象角色和实现角色的分离,实现不同的抽象子类可以与不同的实现子类进行组合,从而可以灵活地处理不同的组合情况。

3.一个类存在多个独立变化的维度,需要支持动态组合。桥接模式能够将各个维度的变化分离,使得每个维度的变化可以独立地扩展,从而可以非常灵活地支持多维度的动态组合。

综上所述,桥接模式适用于具有多个独立变化维度的场景,能够很好地支持这种复杂度。但需要注意的是,若使用不当,桥接模式也可能带来额外的复杂度。因此,应在设计时慎重考虑是否真正需要使用桥接模式。


🍳参考文献

🧊文章总结

提示:这里对文章进行总结:

  本文讲了关于桥接模式的知识。






更多好文推荐

🍸2021-4月Python 机器学习——中文新闻文本标题分类
🍹2021年4月-(计算机网络)小型校园网络模拟搭建,最全最准确版
🍺2022-10-31-基于用户的协同过滤推荐算法实现+MAE+RMSE
🍻2022-11-28-大数据可视化,特征维度大于50
🥂2023-3-9-一篇简短的文章把C++左右值关系讲的透透彻彻

上一篇
End
下一篇

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

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

相关文章

【FFmpeg实战】视频解码流程

原文链接&#xff1a;https://blog.csdn.net/weekend_y45/article/details/125168344 一、解码流程使用到的FFmpeg结构体说明 1、AVFormatContext结构体 该结构体描述了一个媒体文件或媒体流的构成和基本信息。它是一个贯穿始终的数据结构&#xff0c;很多函数调用需要使用到…

【云原生丶Docker】理解Docker的核心概念

Docker的核心优势是什么&#xff1f; 在 什么是虚拟化技术&#xff1f; 一文中&#xff0c;我们对虚拟机和 Docker 都有了简单的了解&#xff0c;需要的小伙伴可以自行跳转回顾~ Docker与传统虚拟化技术有什么区别&#xff1f; Docker 相比传统的虚拟机技术更轻量级&#xff0…

TikTok上的中国商品,老外买上瘾了!

在TikTok的全球影响力下&#xff0c;一些中国商品正实现销量的创纪录增长 2022年底&#xff0c;TikTok发了其第五份“Year on TikTok”年度报告&#xff0c;概述了过去12个月TikTok平台上热度最高的创作者、视频内容&#xff0c;以及#TikTokMadeMeBuyIt标签下最热门的5大产品&…

c语言printf输出格式(%d %f %e %x)

一、%d第一组&#xff1a;%d %nd %-nd第二组&#xff1a;%d %0nd %-0nd %.nd第三组&#xff1a;%d %m.nd %-m.nd 二、%f%f %.nf %m.nf %-m.nf 三、%e%e %.ne %me %-me %m.ne %-m.ed 四、%x%x %0nx %nx %-nx 一、%d 第一组&#xff1a;%d %nd %-nd ①n表示输出宽度&#xff08…

深度学习中使用的16位浮点数格式

深度学习中使用的16位浮点数格式 flyfish 文章目录 深度学习中使用的16位浮点数格式浮点数是一个近似值浮点数的表示float单精度类型 和 double双精度类型 的比较查看所占的字节数大小端的比较计算方法16位 float 半精度格式bflat16格式bflat16格式 与 float32单精度格式 比较…

手敲MyBatis(十二章)-ResultMap解析映射使用

1.前言 这一章节主要解决好几章之前留下的坑&#xff0c;需要根据XML配置的ReultMap进行解析映射成具体的PO供用户使用。 我们本章就来解决下在xml中配置了如下标红框的内容&#xff0c;怎么解析映射到具体的实体类中&#xff0c;如下就是将id为activityMap的resultMap怎么解…

发送图文并茂的html格式的邮件

本文介绍如何生成和发送包含图表和表格的邮件&#xff0c;涉及echarts图表转换为图片、图片内嵌到html邮件内容中、html邮件内容生成、邮件发送方法等 一、图表处理 因为html格式的邮件不支持echarts,也不支持js执行&#xff0c;所以图表需要转换为图片内嵌在邮件内容中 因为平…

Sui Builder House京都站倒计时!

Sui Builder House京都站将于6月29日-30日举行&#xff0c;为世界各地的开发者提供身临其境地学习和交流的机会。查看Sui Builder House京都站的五个亮点 活动信息 &#x1f4c6; Builder House时间&#xff1a;2023年6月29日 — 6月30日 &#x1f4cd; 活动地址&#xff1a;…

NetSuite OAuth1.0中InvalidSignature问题

本周闭关写代码&#xff0c;用Java通过TBA方式访问NetSuite REST Webservices。由于是手生&#xff0c;卡在InvalidSignature报错上&#xff0c;在这个问题上被卡了一整天。 直到终于到来的Aha时刻。 在NetSuite中的样例代码是PHP的&#xff0c; 我平移到Java后&#xff0c;代码…

【云原生丶Docker】虚拟化技术简介

什么是虚拟化技术&#xff1f; Docker 是一款基于容器虚拟化技术构建的软件&#xff0c;那到底什么虚拟化技术呢&#xff1f;在学习 Docker 之前&#xff0c;先简单了解下虚拟化技术。 虚拟化是云原生的实现基础&#xff0c;它能够帮助我们更加有效地利用物理计算机硬件。 虚…

clip-interrogator本地部署

clip-interrogator本地部署 1. 克隆源码2. 创建虚拟环境及配置3. 下载远程相关文件3.1 下载Salesforce相关文件失败3.2 下载cache相关文件失败3.3 解决库不完整问题 4. 测试代码4.1 脚本一4.2 脚本二4.3 测试run_cli.py文件4.4 测试run_gradio.py文件 源码链接&#xff1a;http…

d3dcompiler_47.dll缺失怎么办?d3dcompiler_47.dll缺失修复方法(详解)

d3dcompiler_47.dll在Windows操作系统和 DirectX应用程序中使用此 DLL 文件,包括游戏&#xff0c;图形处理软件&#xff0c;CAD软件和其他3D应用程序中。如果电脑提示“由于找不到d3dcompiler_47.dll&#xff0c;无法继续执行此代码”&#xff0c;“d3dcompiler_47.dll缺失”&a…

Docker卷与持久化数据

数据主要分为两类&#xff0c;持久化的与非持久化的。 两者都很重要&#xff0c;并且Docker均有对应的支持方式。每个Docker容器都有自己的非持久化存储。非持久化存储自动创建&#xff0c;从属于容器&#xff0c;生命周期与容器相同。这意味着删除容器也会删除全部非持久化数…

网络维护岗位个人求职简历

网络维护岗位个人求职简历1 姓名&#xff1a; 国籍&#xff1a;中国 目前所在地&#xff1a;广州民族&#xff1a;汉族 户口所在地&#xff1a;湖南身材&#xff1a;170cm64kg 婚姻状况&#xff1a;未婚年龄&#xff1a;28 求职意向及工作经历 应聘职位&#xff1a; 工作年限&a…

day14_面向对象的三大特征之一(继承)

继承的概述 Java是对现实社会的模拟&#xff0c;现实中有儿子可以继承父亲的财产&#xff0c;因此有了富二代的。 java中多个类中存在相同属性和行为时&#xff0c;将这些内容抽取到单独一个类中&#xff0c;那么多个类中无需再定义这些属性和行为&#xff0c;只需要和抽取出来…

【Java-SpringBoot+Vue+MySql】项目开发杂记

目录 1、关闭eslint 2、 新建路由 3、安装jQuery依赖-在Vue使用JQuery语法 4、MySQL———数据全部清除&#xff0c;自增归零 5、前后端数据传递——增加功能 6、使用element-ui获取当前表格中的数据——删除功能 1、关闭eslint 2、 新建路由 {path: /user,component: Lay…

LLM - Hugging Face 工程 BERT base model (uncased) 配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131400428 BERT是一个在大量英文数据上以自监督的方式预训练的变换器模型。这意味着它只是在原始文本上进行预训练&#xff0c;没有人以…

RabbitMQ实现延迟消息,RabbitMQ使用死信队列实现延迟消息,RabbitMQ延时队列插件

文章目录 一、什么是延迟消息1、队列的属性2、消息的属性3、什么是死信4、使用死信队列的缺点5、延时消息插件 二、JavaAPI利用死信队列实现RabbitMQ延迟消息1、代码实现2、基本流程 三、JavaAPI利用插件实现RabbitMQ延迟消息1、代码实现2、基本原理 四、Springboot利用死信队列…

5分钟自建可视化平台,在线拖拽组件也太方便了!

一、前言 我们在完成 C 端用户的业务需求时&#xff0c;发现大量电商推广页面的逻辑复杂度和交互程度都比较低&#xff0c;却要消耗大量的开发资源。同时在后台管理系统的开发过程中&#xff0c;我们也发现一些相同套路的页面在不同场景下需要重复开发&#xff0c;即使我们封装…

如何提升企业采购绩效?提高采购绩效的方法

采购是任何企业的一个重要方面&#xff0c;它在确保企业平稳高效运行方面发挥着重要作用。作为一名采购专业人员&#xff0c;你有责任确保你的企业以正确的质量、数量和价格获得所需的货物和服务。 本文将讨论一些最佳做法&#xff0c;这些做法可以帮助你提高采购专业人员的绩…