23种设计模式-装饰器(Decorator)设计模式

news2024/11/28 17:58:03

文章目录

  • 一.什么是装饰器设计模式?
  • 二.装饰器模式的特点
  • 三.装饰器模式的结构
  • 四.装饰器模式的优缺点
  • 五.装饰器模式的 C++ 实现
  • 六.装饰器模式的 Java 实现
  • 七.代码解析
  • 八.总结

类图: 装饰器设计模式类图

一.什么是装饰器设计模式?

装饰器模式(Decorator Pattern) 是一种结构型设计模式。它允许在运行时动态地为对象添加新的功能,而无需修改其代码。装饰器模式通过将对象嵌套在装饰器对象中,实现了功能的动态扩展,同时遵循了开放-关闭原则

二.装饰器模式的特点

  • 运行时动态扩展:通过嵌套装饰器对象,可以动态地为对象增加功能。
  • 与继承的区别:装饰器通过组合来扩展对象功能,而不是通过继承,避免了类爆炸问题。
  • 灵活性:可以使用多个装饰器类,按照需要灵活组合功能。

三.装饰器模式的结构

  • Component(组件接口):定义一个对象接口,可以动态地为其增加职责。
  • ConcreteComponent(具体组件):实现基础功能的类。
  • Decorator(抽象装饰器):实现 Component 接口,并包含一个指向 Component 对象的引用。
  • ConcreteDecorator(具体装饰器):实现额外的功能,并调用组件对象的原有功能。
    装饰器设计模式

四.装饰器模式的优缺点

  • 优点:
    • 动态扩展:可以动态地为对象添加功能。
    • 遵循开放-关闭原则:无需修改原有类的代码即可扩展功能。
    • 灵活性:装饰器可以灵活组合,扩展方式更具弹性。
  • 缺点:
    • 复杂性增加:使用多个装饰器会导致类数量增多,结构变得复杂。
    • 调试困难:由于功能是动态组合的,调试时可能难以定位问题来源。

五.装饰器模式的 C++ 实现

#include <iostream>
#include <memory>
using namespace std;

// 抽象组件
class Component {
public:
    virtual void Operation() const = 0;
    virtual ~Component() = default;
};

// 具体组件
class ConcreteComponent : public Component {
public:
    void Operation() const override {
        cout << "ConcreteComponent: Performing operation." << endl;
    }
};

// 抽象装饰器
class Decorator : public Component {
protected:
    shared_ptr<Component> component; // 持有组件的引用
public:
    Decorator(shared_ptr<Component> comp) : component(move(comp)) {}
    void Operation() const override {
        if (component) {
            component->Operation();
        }
    }
};

// 具体装饰器A
class ConcreteDecoratorA : public Decorator {
public:
    ConcreteDecoratorA(shared_ptr<Component> comp) : Decorator(move(comp)) {}
    void Operation() const override {
        Decorator::Operation(); // 调用原始组件的功能
        AddedBehavior();        // 添加新行为
    }
private:
    void AddedBehavior() const {
        cout << "ConcreteDecoratorA: Adding behavior A." << endl;
    }
};

// 具体装饰器B
class ConcreteDecoratorB : public Decorator {
public:
    ConcreteDecoratorB(shared_ptr<Component> comp) : Decorator(move(comp)) {}
    void Operation() const override {
        Decorator::Operation(); // 调用原始组件的功能
        AddedBehavior();        // 添加新行为
    }
private:
    void AddedBehavior() const {
        cout << "ConcreteDecoratorB: Adding behavior B." << endl;
    }
};

// 客户端代码
int main() {
    shared_ptr<Component> simple = make_shared<ConcreteComponent>();
    cout << "Client: Using a simple component:" << endl;
    simple->Operation();

    shared_ptr<Component> decoratorA = make_shared<ConcreteDecoratorA>(simple);
    cout << "\nClient: Using a component decorated with A:" << endl;
    decoratorA->Operation();

    shared_ptr<Component> decoratorB = make_shared<ConcreteDecoratorB>(decoratorA);
    cout << "\nClient: Using a component decorated with A and B:" << endl;
    decoratorB->Operation();

    return 0;
}

六.装饰器模式的 Java 实现

// 抽象组件
interface Component {
    void operation();
}

// 具体组件
class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent: Performing operation.");
    }
}

// 抽象装饰器
abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }
}

// 具体装饰器A
class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation(); // 调用原始组件的功能
        addedBehavior();
    }

    private void addedBehavior() {
        System.out.println("ConcreteDecoratorA: Adding behavior A.");
    }
}

// 具体装饰器B
class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation(); // 调用原始组件的功能
        addedBehavior();
    }

    private void addedBehavior() {
        System.out.println("ConcreteDecoratorB: Adding behavior B.");
    }
}

// 客户端代码
public class DecoratorPatternExample {
    public static void main(String[] args) {
        Component simple = new ConcreteComponent();
        System.out.println("Client: Using a simple component:");
        simple.operation();

        Component decoratorA = new ConcreteDecoratorA(simple);
        System.out.println("\nClient: Using a component decorated with A:");
        decoratorA.operation();

        Component decoratorB = new ConcreteDecoratorB(decoratorA);
        System.out.println("\nClient: Using a component decorated with A and B:");
        decoratorB.operation();
    }
}

七.代码解析

  • 抽象组件(Component)
    • 提供统一接口 Operation,供所有具体组件和装饰器实现。
    • 使得客户端代码可以以相同的方式使用组件和装饰器。
  • 具体组件(ConcreteComponent)
    • 实现基础功能,例如打印操作信息。
  • 抽象装饰器(Decorator)
    • 持有一个 Component 类型的指针,代表被装饰的对象。
    • 定义通用的装饰行为,默认直接调用被装饰对象的 Operation 方法。
  • 具体装饰器(ConcreteDecoratorA/B)
    • 通过扩展 Decorator 类,增加特定功能。
    • AddedBehavior 方法实现装饰器的额外行为,例如打印装饰信息。
  • 使用 shared_ptr
    • 动态管理对象内存,避免手动管理导致的内存泄漏。

八.总结

 装饰器模式提供了一种灵活的方式来动态扩展对象的功能,避免了继承导致的类膨胀问题。通过引入抽象装饰器和具体装饰器,装饰器模式实现了功能的动态组合,使得代码更易于维护和扩展。
应用场景:

  • 动态扩展对象功能:需要在不修改对象代码的情况下,为对象添加功能。
  • 替代子类扩展:避免因为子类扩展功能导致的类爆炸问题。
  • 灵活组合功能:需要根据不同的条件动态组合对象的功能。

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

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

相关文章

构建英语知识网站:Spring Boot框架解析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

数据结构之数组与链表的差异

一、数组 数组&#xff08;Array&#xff09;是由相同类型的元素&#xff08;element&#xff09;的集合所组成的数据结构&#xff0c;分配一块连续的内存来存储。利用元素的索引&#xff08;index&#xff09;可以计算出该元素对应的存储地址。最简单的数据结构类型是一维数组…

RabbitMQ7:消息转换器

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

Ubuntu20.04+ROS 进行机械臂抓取仿真:环境搭建(一)

目录 一、从官网上下载UR机械臂 二、给UR机械臂添加夹爪 三、报错解决 本文详细介绍如何在Ubuntu20.04ROS环境中为Universal Robots的UR机械臂添加夹爪。首先从官方和第三方源下载必要的软件包&#xff0c;包括UR机械臂驱动、夹爪插件和相关依赖。然后&#xff0c;针对gazeb…

(即插即用模块-Attention部分) 二十、(2021) GAA 门控轴向注意力

文章目录 1、Gated Axial-Attention2、代码实现 paper&#xff1a;Medical Transformer: Gated Axial-Attention for Medical Image Segmentation Code&#xff1a;https://github.com/jeya-maria-jose/Medical-Transformer 1、Gated Axial-Attention 论文首先分析了 ViTs 在训…

Git 进程占用报错-解决方案

背景 大仓库&#xff0c;由于开发者分支较多&#xff0c;我们在使用 git pull 或 git push 等命令时&#xff08;与远端仓库交互的命令&#xff09;&#xff0c;不知之前配置了什么&#xff0c;我的电脑会必现以下报错&#xff08;有非常长一大串报错-不同分支的git进程占用报…

【FPGA-MicroBlaze】串口收发以及相关函数讲解

前言 工具&#xff1a;Vivado2018.3及其所对应的SDK版本 目前网上有许多MicroBlaze 的入门教程&#xff0c;比如下面的这个参考文章&#xff0c;用串口打印一个hello world。 【FPGA】Xilinx MicroBlaze软核使用第一节&#xff1a;Hello World!_fpga软核microblaze-CSDN博客 个…

代码美学2:MATLAB制作渐变色

效果&#xff1a; %代码美学&#xff1a;MATLAB制作渐变色 % 创建一个10x10的矩阵来表示热力图的数据 data reshape(1:100, [10, 10]);% 创建热力图 figure; imagesc(data);% 设置颜色映射为“cool” colormap(cool);% 在热力图上添加边框 axis on; grid on;% 设置热力图的颜色…

Android下载出现open failed: EPERM (Operation not permitted)

今天帮忙给同事调一下apk&#xff0c;发现android 自动更新apk&#xff0c;下载apk的时候总是失败&#xff0c;总是卡在 输出流这一步了 于是第一步分析&#xff0c;立马想到权限 但是下载之前的读写内存的权限也都有了 什么android 10高版本的不开启分区存储也用了 android…

使用爬虫时,如何确保数据的准确性?

在数字化时代&#xff0c;数据的准确性对于决策和分析至关重要。本文将探讨如何在使用Python爬虫时确保数据的准确性&#xff0c;并提供代码示例。 1. 数据清洗 数据清洗是确保数据准确性的首要步骤。在爬取数据后&#xff0c;需要对数据进行清洗&#xff0c;去除重复、无效和…

uniapp中使用Mescroll实现下拉刷新与上拉加载项目实战

如何在UniApp中使用Mescroll实现下拉刷新与上拉加载 前言 下拉刷新和上拉加载更多成为了提升用户体验不可或缺的功能。UniApp作为一个跨平台的应用开发框架&#xff0c;支持使用Vue.js语法编写多端&#xff08;iOS、Android、H5等&#xff09;应用。Mescroll作为一款专为Vue设…

【接口自动化测试】一文从0到1详解接口测试协议!

接口自动化测试是软件开发过程中重要的环节之一。通过对接口进行测试&#xff0c;可以验证接口的功能和性能&#xff0c;确保系统正常运行。本文将从零开始详细介绍接口测试的协议和规范。 定义接口测试协议 接口测试协议是指用于描述接口测试的规范和约定。它包含了接口的请求…

RAG数据拆分之PDF

引言RAG数据简介PDF解析方法及工具代码实现总结 二、正文内容 引言 本文将介绍如何将RAG数据拆分至PDF格式&#xff0c;并探讨PDF解析的方法和工具&#xff0c;最后提供代码示例。 RAG数据简介 RAG&#xff08;关系型属性图&#xff09;是一种用于表示实体及其关系的图数据…

【开源项目】2024最新PHP在线客服系统源码/带预知消息/带搭建教程

简介 随着人工智能技术的飞速发展&#xff0c;AI驱动的在线客服系统已经成为企业提升客户服务质量和效率的重要工具。本文将探讨AI在线客服系统的理论基础&#xff0c;并展示如何使用PHP语言实现一个简单的AI客服系统。源码仓库地址&#xff1a;ym.fzapp.top 在线客服系统的…

WEB攻防-通用漏洞XSS跨站MXSSUXSSFlashXSSPDFXSS

演示案例&#xff1a; UXSS-Edge&CVE-2021-34506 FlashXSS-PHPWind&SWF反编译 PDFXSS-PDF动作添加&文件上传 使用jpexs反编译swf文件 上传后&#xff0c;发给别人带漏洞的分享链接

QSqlTableModel的使用

实例功能 这边使用一个实例显示数据库 demodb 中 employee 数据表的内容&#xff0c;实现编辑、插入、删除的操作&#xff0c;实现数据的排序和记录过滤&#xff0c;还实现 BLOB 类型字段 Photo 中存储照片的显示、导入等操作&#xff0c;运行界面如下图&#xff1a; 在上图中…

适用于学校、医院等低压用电场所的智能安全配电装置

引言 电力&#xff0c;作为一种清洁且高效的能源&#xff0c;极大地促进了现代生活的便捷与舒适。然而&#xff0c;与此同时&#xff0c;因使用不当或维护缺失等问题&#xff0c;漏电、触电事件以及电气火灾频发&#xff0c;对人们的生命安全和财产安全构成了严重威胁&#xf…

LabVIEW实现UDP通信

目录 1、UDP通信原理 2、硬件环境部署 3、云端环境部署 4、UDP通信函数 5、程序架构 6、前面板设计 7、程序框图设计 8、测试验证 本专栏以LabVIEW为开发平台&#xff0c;讲解物联网通信组网原理与开发方法&#xff0c;覆盖RS232、TCP、MQTT、蓝牙、Wi-Fi、NB-IoT等协议。 结合…

java——Spring MVC的工作流程

Spring MVC的工作流程是基于模型-视图-控制器&#xff08;MVC&#xff09;设计模式的一个典型实现&#xff0c;以下是其主要工作流程步骤&#xff1a; 客户端请求提交&#xff1a; 用户通过浏览器向服务器发送请求&#xff0c;该请求首先到达Spring MVC的前端控制器DispatcherS…

带有悬浮窗功能的Android应用

android api29 gradle 8.9 要求 布局文件 (floating_window_layout.xml): 增加、删除、关闭按钮默认隐藏。使用“开始”按钮来控制这些按钮的显示和隐藏。 服务类 (FloatingWindowService.kt): 实现“开始”按钮的功能&#xff0c;点击时切换增加、删除、关闭按钮的可见性。处…