二十三种设计模式-装饰器模式

一、定义与核心思想

装饰器模式是一种结构型设计模式,其核心思想是动态地给一个对象添加一些额外的职责。通过这种方式,可以在不改变原有对象结构的基础上,灵活地增加新的功能,使得对象的行为可以得到扩展,同时又保持了原有类的简洁性。

二、组成要素

装饰器模式主要由以下几个要素组成:

  1. 抽象组件(Component)

    • 这是一个接口或抽象类,用于定义对象的接口,即声明了所有具体组件和装饰器类都需要实现的方法。它使得装饰器类可以与被装饰的具体组件类在接口上保持一致,从而可以在运行时动态地组合对象。

    • 例如,定义一个Component接口,其中声明了一个operation()方法。

  2. 具体组件(ConcreteComponent)

    • 实现抽象组件接口的具体类,它定义了对象的基本行为和状态,是被装饰的具体对象。

    • 例如,ConcreteComponent类实现了Component接口,在operation()方法中实现了具体的功能。

  3. 抽象装饰器(Decorator)

    • 也实现了抽象组件接口,它内部包含了一个对抽象组件的引用,通过这个引用可以调用被装饰对象的方法。抽象装饰器类中还定义了一些新的方法或属性,用于添加新的功能。

    • 例如,Decorator类实现了Component接口,并且有一个Component类型的成员变量component,在operation()方法中先调用component.operation(),然后添加新的行为。

  4. 具体装饰器(ConcreteDecorator)

    • 继承自抽象装饰器类,实现了添加具体功能的方法。每个具体装饰器类都实现了在抽象装饰器中声明的添加功能的方法,并且可以有自己独特的功能。

    • 例如,ConcreteDecoratorAConcreteDecoratorB都是Decorator的子类,在它们的operation()方法中分别添加了不同的新功能。

三、实现示例

以下是使用Java语言实现装饰器模式的一个简单示例:

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

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

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

    public void setComponent(Component component) {
        this.component = component;
    }

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

// 具体装饰器A类
class ConcreteDecoratorA extends Decorator {
    private String addedState;

    @Override
    public void operation() {
        super.operation();
        addedState = "New State";
        System.out.println("具体装饰器A的操作");
    }
}

// 具体装饰器B类
class ConcreteDecoratorB extends Decorator {
    @Override
    public void operation() {
        super.operation();
        addedBehavior();
        System.out.println("具体装饰器B的操作");
    }

    private void addedBehavior() {
        // 添加新的行为
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        ConcreteDecoratorA decoratorA = new ConcreteDecoratorA();
        ConcreteDecoratorB decoratorB = new ConcreteDecoratorB();

        decoratorA.setComponent(component);
        decoratorB.setComponent(decoratorA);

        decoratorB.operation();
    }
}

在这个示例中,客户端代码首先创建了一个具体组件对象component,然后创建了两个具体装饰器对象decoratorAdecoratorB。通过setComponent方法将component对象与装饰器对象关联起来,并且装饰器对象之间也可以相互关联。最后调用decoratorB.operation()方法时,会依次调用decoratorA.operation()component.operation()方法,并在每个装饰器中添加新的行为。

四、优点

  1. 扩展性好

    • 可以通过添加新的装饰器类来扩展对象的功能,而无需修改原有的组件类代码,符合开闭原则。

  2. 灵活性高

    • 可以根据需要动态地添加或组合不同的装饰器,以达到不同的功能效果,比静态继承方式更加灵活。

  3. 避免了复杂的继承关系

    • 如果使用继承来扩展功能,可能会导致大量的子类产生,而装饰器模式可以避免这种情况,使系统更加简洁。

五、缺点

  1. 可能会产生很多小类

    • 每个装饰器类都是一个小类,如果装饰器很多,可能会导致类的数量急剧增加,增加了系统的复杂性。

  2. 调试难度较大

    • 由于装饰器的动态组合,可能会使得对象的行为变得难以跟踪和调试,特别是当装饰器层次较多时。

六、应用场景

  1. 功能扩展

    • 当需要给一个对象动态地添加额外的功能时,如给文本组件添加边框、颜色、字体等装饰效果。

  2. 增强对象行为

    • 在不改变原有对象的基础上,增强对象的行为,如在网络通信中,对数据进行加密、压缩等处理,可以通过装饰器模式动态地添加这些功能。

  3. 多层装饰

    • 当需要对对象进行多层装饰,以组合出多种不同的功能效果时,装饰器模式能够很好地满足需求,如在构建复杂的用户界面组件时,通过多个装饰器来实现不同的视觉效果和交互行为。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx 配置代理,根据 不同的请求头进行转发至不同的代理

解决场景:下载发票的版式文件,第三方返回的是url链接地址,但是服务是部署在内网环境,无法访问互联网进行下载。此时需要进行走反向代理出去,如果按照已有套路,就是根据不同的访问前缀,跳转不同的…

EI Scopus双检索 | 2025年第四届信息与通信工程国际会议(JCICE 2025)

会议简介 Brief Introduction 2025年第四届信息与通信工程国际会议(JCICE 2025) 会议时间:2025年7月25日-27日 召开地点:中国哈尔滨 大会官网:www.jcice.org 由黑龙江大学和成都信息工程大学主办,江苏科技大学协办的2025年第四届信…

软考高级5个资格、中级常考4个资格简介及难易程度排序

一、软考高级5个资格 01、网络规划设计师 资格简介:网络规划设计师要求考生具备全面的网络规划、设计、部署和管理能力;该资格考试适合那些在网络规划和设计方面具有较好理论基础和较丰富从业经验的人员参加。 02、系统分析师 资格简介:系统分…

STM32 FreeRTOS 任务挂起和恢复---实验

实验目标 学会vTaskSuspend( )、vTaskResume( ) 任务挂起与恢复相关API函数使用: start_task:用来创建其他的三个任务。 task1:实现LED1每500ms闪烁一次。 task2:实现LED2每500ms闪烁一次。 task3:判断按键按下逻辑,KE…

YOLO系列代码

Test-Time Augmentation TTA (Test Time Augmentation)是指在test过程中进行数据增强。其思想非常简单,就是在评测阶段,给每个输入进行多种数据增广变换,将一个输入变成多个输入,然后再merge起来一起输出,形成一种ens…

《自动驾驶与机器人中的SLAM技术》ch4:基于预积分和图优化的 GINS

前言:预积分图优化的结构 1 预积分的图优化顶点 这里使用 《自动驾驶与机器人中的SLAM技术》ch4:预积分学 中提到的散装的形式来实现预积分的顶点部分,所以每个状态被分为位姿()、速度、陀螺零偏、加计零偏四种顶点&am…

docker 部署confluence

1.安装docker的过程就不说了。 2.下载镜像。 docker pull cptactionhank/atlassian-confluence:7.4.0 docker images 3.下载pojie 包。 https://download.csdn.net/download/liudongyang123/90285042https://download.csdn.net/download/liudongyang123/90285042https://do…

前端实习第二个月小结

时间飞快,第一次实习已经过去两个多月,作一些简单的总结和分享。 注:文章整体会比较轻松,提及的经历、经验仅作参考。 一、关于实习/工作内容 1、工作内容 近期做的是管理后台方面的业务,技术栈:前端re…

搭建一个基于Spring Boot的书籍学习平台

搭建一个基于Spring Boot的书籍学习平台可以涵盖多个功能模块,例如用户管理、书籍管理、学习进度跟踪、笔记管理、评论和评分等。以下是一个简化的步骤指南,帮助你快速搭建一个基础的书籍学习平台。 — 1. 项目初始化 使用 Spring Initializr 生成一个…

dl学习笔记:(4)简单神经网络

(1)单层正向回归网络 bx1x2z100-0.2110-0.05101-0.051110.1 接下来我们用代码实现这组线性回归数据 import torch x torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype torch.float32) z torch.tensor([-0.2, -0.05, -0.05, 0.1]) w torch.…

OpenHarmony-7.IDL工具

IDL 工具 1.openharmony IDL工具 在OpenHarmony中,当应用/系统服务的客户端和服务端进行IPC(Inter-Process Communication)跨线程通信时,需要定义双方都认可的接口,以保障双方可以成功通信,OpenHarmony ID…

openssl s_server源码剥离

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

前端小案例——网页井字棋

前言:我们在学习完了HTML、CSS和JavaScript之后,就会想着使用这三个东西去做一些小案例,不过又没有什么好的案例让我们去练手,本篇文章就提供里一个案例——网页井字棋。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可…

Leetcode 983. 最低票价 动态规划

原题链接&#xff1a;Leetcode 983. 最低票价 class Solution { public:int mincostTickets(vector<int>& days, vector<int>& costs) {int n days.size();int last days[n - 1];int dp[last 1];map<int, int> mp;for (auto x : days)mp[x] 1;dp…

Java中的 锁现象演示和原理解释 多线程操作资源类 八种案例 同步方法 静态方法 对象锁 类锁

目录 面试题 案例 1 标准访问有 ab 两个线程 案例 2 其中一个同步方法暂停 3 秒 案例 3 新增普通方法 案例 4 创建两个对象 案例 5 两个静态同步方法 一个对象 案例 6 两个静态同步方法 两个对象 案例 7 一个静态同步方法 一个普通同步方法 一个对象 案例 8 一个静态同…

HTML应用指南:利用GET请求获取全国特斯拉充电桩位置

随着电动汽车的普及&#xff0c;充电基础设施的建设变得至关重要。作为电动汽车领域的先驱&#xff0c;特斯拉不仅在车辆技术创新上持续领先&#xff0c;还积极构建广泛的充电网络&#xff0c;以支持其不断增长的用户群体。为了提升用户体验和服务质量&#xff0c;开发人员和数…

cuda + cudnn安装

1.安装CUDA Toolkit 在设备管理器&#xff08;此电脑–右键–属性&#xff09;的显示适配器中可以查看自己的显卡型号&#xff0c;去下载对应的CUDA Toolkit 。或者输入以下命令查看Driver Version &#xff0c;cuda Version&#xff1a;12.2代表12.2版本以下兼容可以进行安装 …

【k8s面试题2025】1、练气期

主要通过呼吸吐纳等方法&#xff0c;将外界的天地灵气吸入体内&#xff0c;初步改造身体&#xff0c;使身体素质远超常人。 文章目录 docker 和虚拟机的不同Kubernetes 和 docker 的关系Kube-proxy IPVS 和 iptables 的异同蓝绿发布Kubernetes中常见的数据持久化方式关于 Docke…

vue | 插值表达式

Vue 是一个用于 构建用户界面 的 渐进式 框架 1. 构建用户界面&#xff1a;基于 数据 动态 渲染 页面 2. 渐进式&#xff1a;循序渐进的学习 3. 框架&#xff1a;一套完整的项目解决方案&#xff0c;提升开发效率↑ (理解记忆规则) 插值表达式&#xff1a; 插值表达式是一种 Vu…

【蜂巢——方向,数学】

题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; int dx[6] {-1, -1, 0, 1, 1, 0}; int dy[6] {0, 1, 1, 0, -1, -1}; void cal(int d, int p, int q, int& x, int& y) {x p * dx[d];y p * dy[d];d (d 2) % 6;x q * dx[d];…