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

【设计模式-结构型】装饰器模式

一、什么是装饰器模式

        装饰器模式(Decorator Pattern)是一种结构型设计模式,它的核心思想是在不改变原有对象结构的情况下,动态地给对象增加一些功能,从而达到扩展功能的目的。举个例子,今天在家妈妈给蒸馒头。馒头蒸的过程中,妈妈去收拾衣服了。突然想起来,馒头好了,就跟你说:“帮我把馒头拿出来。”这个时候馒头特别烫,如果不烫其实用我们的手是可以拿出来的,但是这个时候光用手拿不行。所以我们想了个办法,找了一个手套,从而把馒头拿了出来。这个过程就类似于装饰器模式,手套相当于装饰器,给手(原有对象)增加了隔热的功能,使得手能够处理原本无法直接处理的烫馒头。

二、为什么使用装饰器模式

        基于上面的馒头场景,我们讨论一下为什么使用装饰器模式(为什么要戴手套):

  1. 动态扩展(撤销)功能:当需要在运行时为对象动态添加功能时,装饰器模式是一个很好的选择。例如,比如应对热馒头去拿的时候要隔热功能,不想隔热还可以直接上手。但是装饰的多了,手不热吗?手不累吗?所示要适当添加。别为了拿馒头装了一堆东西反而得不偿失。

  2. 避免子类爆炸:如果通过继承来扩展功能,可能会导致子类数量急剧增加,使得系统变得复杂且难以维护。装饰器模式可以避免这种情况,通过组合的方式动态添加功能(继承关系的替代)。

  3. 保持原有接口不变:装饰器模式可以在不改变原有对象接口的情况下,增加新的功能,这使得客户端代码可以透明地使用被装饰的对象,而不需要修改客户端代码。(拿馒头的手,拿的功能不变

三、装饰器模式示例

  1. Component(抽象组件):定义了被装饰对象的接口,所有具体的组件和装饰器都实现这个接口。

    //我就是一个手,人们定义我叫手,收能拿东西
    public interface Hand {void pickUp(Object object) throws Exception;
    }
  2. ConcreteComponent(具体组件):实现了Component接口的具体组件,是被装饰的对象。

    //我是一个赤裸裸真是长在身上的手,人们说手可以拿东西,我也可以
    public class BareHand implements Hand {@Overridepublic void pickUp(Object object) throws Exception {if (object instanceof HotBun) {throw new Exception("我擦,太热了!");}System.out.println("Picked up " + object.getClass().getSimpleName() + " with bare hands.");}
    }
  3. Decorator(装饰器抽象类):也实现了Component接口,持有一个Component对象的引用,通过组合的方式动态地为Component对象添加新的功能。

    //其实手上没准可以加点东西 
    public abstract class HandDecorator implements Hand {protected Hand hand;public HandDecorator(Hand hand) {this.hand = hand;}@Overridepublic void pickUp(Object object) throws Exception {hand.pickUp(object);}
    }
  4. ConcreteDecorator(具体装饰器):实现了Decorator的具体装饰器,负责给Component对象添加具体的装饰功能。

    //我是手套
    public class GloveDecorator extends HandDecorator {public GloveDecorator(Hand hand) {super(hand);}@Overridepublic void pickUp(Object object) throws Exception {System.out.println("戴上手套去拿 " + object.getClass().getSimpleName());hand.pickUp(object);}
    }
  5. 客户端

    //我是一个热馒头
    public class HotBun {// 烫馒头的具体实现
    }
    public class Main {public static void main(String[] args) {Hand bareHand = new BareHand();try {bareHand.pickUp(new HotBun());} catch (Exception e) {System.out.println(e.getMessage());}// 使用手套装饰手Hand glovedHand = new GloveDecorator(bareHand);try {glovedHand.pickUp(new HotBun());} catch (Exception e) {System.out.println(e.getMessage());}}
    }//输出
    我擦,太热了!
    戴上手套去拿热馒头
    我擦,太热了!

相关文章:

【设计模式-结构型】装饰器模式

一、什么是装饰器模式 装饰器模式(Decorator Pattern)是一种结构型设计模式,它的核心思想是在不改变原有对象结构的情况下,动态地给对象增加一些功能,从而达到扩展功能的目的。举个例子,今天在家妈妈给蒸馒…...

分布式数据存储基础与HDFS操作实践(副本)

以下为作者本人撰写的报告,步骤略有繁琐,不建议作为参考内容,可以适当浏览,进一步理解。 一、实验目的 1、理解分布式文件系统的基本概念和工作原理。 2、掌握Hadoop分布式文件系统(HDFS)的基本操作。 …...

Linux 进程前篇(冯诺依曼体系结构和操作系统)

目录 一.冯诺依曼体系结构 1.概念 2.硬件层面的数据流 3.总结加补充 二.操作系统 (Operating System) 1.概念 2.设计OS的目的 3.定位 4.操作系统的管理 5.计算机体系的层状结构 在我们认识进程之前,我们先了解什么是冯诺依曼体系结构 一.冯诺依曼体系结构…...

Springboot Redisson 分布式锁、缓存、消息队列、布隆过滤器

redisson-spring-boot-starter 是 Redisson 提供的 Spring Boot 集成包&#xff0c;旨在简化与 Redis 的交互&#xff0c;包括分布式锁、缓存、消息队列、布隆过滤器等功能的实现。 Maven 依赖 在 Spring Boot 项目中添加 redisson-spring-boot-starter 依赖&#xff1a; <…...

【C语言】_字符串拷贝函数strcpy

目录 1. 函数声明及功能 2. 使用示例 3. 注意事项 4. 模拟实现 4.1 第一版&#xff1a;基本功能判空const修饰 4.2 第二版&#xff1a;优化对于\0的单独拷贝 4.3 第三版&#xff1a;仿strcpy的char*返回值 1. 函数声明及功能 char * strcpy ( char * destination, cons…...

基于 Vue 的拖拽缩放卡片组件:实现思路、方法及使用指南

引言 在前端开发中&#xff0c;实现可交互的组件能够极大地提升用户体验。本文将介绍一个基于 Vue 封装的可缩放卡片组件&#xff0c;从实现思路、代码具体实现以及使用方法等方面进行详细阐述&#xff0c;帮助开发者更好地理解和运用这一组件。项目源码地址&#xff1a;https…...

nginx 实现 正向代理、反向代理 、SSL(证书配置)、负载均衡 、虚拟域名 ,使用其他中间件监控

我们可以详细地配置 Nginx 来实现正向代理、反向代理、SSL、负载均衡和虚拟域名。同时&#xff0c;我会介绍如何使用一些中间件来监控 Nginx 的状态和性能。 1. 安装 Nginx 如果你还没有安装 Nginx&#xff0c;可以通过以下命令进行安装&#xff08;以 Ubuntu 为例&#xff0…...

Kafka客户端-“远程主机强迫关闭了一个现有的连接”故障排查及解决

Kafka客户端-“远程主机强迫关闭了一个现有的连接”故障排查及解决 1. 故障现象 Kafka客户端发送数据时&#xff0c;出现“远程主机强迫关闭了一个现有的连接”错误&#xff0c;导致数据发送失败。错误信息如下&#xff1a; 2. 故障排查 【1】. 查看服务网络状态 出现故障…...

Node.js - Express框架

1. 介绍 Express 是一个基于 Node.js 的 Web 应用程序框架&#xff0c;主要用于快速、简便地构建 Web 应用程序 和 API。它是目前最流行的 Node.js Web 框架之一&#xff0c;具有轻量级、灵活和功能丰富的特点。 核心概念包括路由&#xff0c;中间件&#xff0c;请求与响应&a…...

AWS Lambda

AWS Lambda 是 Amazon Web Services&#xff08;AWS&#xff09;提供的无服务器计算服务&#xff0c;它让开发者能够运行代码而不需要管理服务器或基础设施。AWS Lambda 会自动处理代码的执行、扩展和计费&#xff0c;开发者只需关注编写和部署代码&#xff0c;而无需担心底层硬…...

mysql 如何快速删除表数据

在数据库管理中, 经常会遇到需要删除大量数据的情况. 对于 MySQL 数据库而言, 如何高效快速地删除数据是一个值得深入探讨的问题. 本文将详细介绍几种在 MySQL 中快速删除数据的方法及相关注意事项. delete 语句 delete 语句可以删除符合条件的指定数据, 但是在删除大量数据…...

物联网网关Web服务器--lighttpd服务器部署与应用测试

以下是在国产ARM处理器E2000飞腾派开发板上部署 lighttpd 并进行 CGI 应用开发的步骤&#xff1a; 1、lighttpd简介 Lighttpd 是一款轻量级的开源 Web 服务器软件&#xff0c;具有以下特点和功能&#xff1a; 特点 轻量级&#xff1a;Lighttpd 在设计上注重轻量级和高效性&a…...

vmware虚拟机配置ubuntu 18.04(20.04)静态IP地址

VMware版本 &#xff1a;VMware Workstation 17 Pro ubuntu版本&#xff1a;ubuntu-18.04.4-desktop-amd64 主机环境 win11 1. 修改 VMware虚拟网络编辑器 打开vmware&#xff0c;点击顶部的“编辑"菜单&#xff0c;打开 ”虚拟化网络编辑器“ 。 选择更改设置&#…...

智能家居篇 一、Win10 VM虚拟机安装 Home Assistant 手把手教学

智能家居篇 一、Win10 VM虚拟机安装 Home Assistant 手把手教学 文章目录 [智能家居篇]( )一、Win10 VM虚拟机安装 Home Assistant 手把手教学 前言一.下载Vm版本的HomeAsistant安装包 二.打开Vmware选择新建虚拟机1.选择自定义高级2.选择16.x及以上3.选择稍后安装4.根据官网的…...

Flutter插件制作、本地/远程依赖及缓存机制深入剖析(原创-附源码)

Flutter插件在开发Flutter项目的过程中扮演着重要的角色&#xff0c;我们从 ​​​​​​https://pub.dev 上下载添加到项目中的第三方库都是以包或者插件的形式引入到代码中的&#xff0c;这些第三方工具极大的提高了开发效率。 深入的了解插件的制作、发布、工作原理和缓存机…...

Python猜数小游戏

Python 实现的《猜数游戏》 介绍 本文将展示如何使用 Python 编写一个简单的《猜数游戏》。这个游戏将会生成一个1到10之间的随机数&#xff0c;用户有最多三次机会来猜测正确的数字。如果用户猜对了&#xff0c;游戏将结束并显示恭喜信息&#xff1b;如果没有猜对&#xff0…...

--- 用java实现一个计时器 ---

这里的计时器值得是当线程设定的时间过了之后&#xff0c;自动执行该线程的工作 设计 MyTimer 既然是要在指定的时间之后执行任务&#xff0c;那么传入的参数就应该有run方法&#xff08;需要执行的任务&#xff09;&#xff0c;time&#xff08;在多少时间之后执行&#xff…...

OPI4A,目标检测,口罩检测,mnn,YoloX

记得之前&#xff0c;使用了bubbling导师复现的python版yolox&#xff0c;训练了自建的口罩数据集&#xff0c;得到了h5文件&#xff0c;又转换成pb文件&#xff0c;再使用阿里巴巴的MNN&#xff0c;使用它的MNNConvert&#xff0c;转换成mnn文件 最终实现了&#xff0c;在树莓…...

C#与Vue2上传下载Excel文件

1、上传文件流程&#xff1a;先上传文件&#xff0c;上传成功&#xff0c;返回文件名与url&#xff0c;然后再次发起请求保存文件名和url到数据库 前端Vue2代码&#xff1a; 使用element的el-upload组件&#xff0c;action值为后端接收文件接口&#xff0c;headers携带session信…...

Linux(Centos7)安装Mysql/Redis/MinIO

安装Mysql 安装Redis 搜索Redis最先版本所在的在线安装yum库 查看以上两个组件是否是开机自启 安装MinIO 开源的对象存储服务&#xff0c;存储非结构化数据&#xff0c;兼容亚马逊S3协议。 minio --help #查询命令帮助minio --server --help #查询--server帮助minio serve…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...