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

Java设计模式之装饰器(Decorator)模式

装饰器(Decorator)设计模式允许动态地将新功能添加到对象中,同时又不改变其结构。

什么是装饰器模式

装饰器(Decorator)模式通过将对象进行包装,以扩展其功能,而不需要修改其原始类。装饰器模式基于组合而非继承的原则,通过递归和委托来创建具有新功能的对象。

装饰器模式的使用场景

装饰器(Decorator)模式适用于以下情况:

  • 需要在运行时为对象添加额外的行为,而不影响其他对象。
  • 需要动态地为对象添加新的功能,而又不希望生成大量的子类。

装饰器模式的代码示例

下面是一个简单的示例,我们将使用装饰器模式来扩展一个咖啡店中的咖啡品种,如添加牛奶、糖等。我们将创建一个基础的咖啡接口,然后使用装饰器类来扩展可选的配料。下面是代码实现:

// 咖啡接口
interface Coffee {String getIngredients(); // 获取咖啡配料double getPrice(); // 获取咖啡价格
}// 基础咖啡类
class SimpleCoffee implements Coffee {public String getIngredients() {return "Coffee";}public double getPrice() {return 2.0;}
}// 咖啡装饰器基类
abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}public String getIngredients() {return coffee.getIngredients();}public double getPrice() {return coffee.getPrice();}
}// 牛奶咖啡装饰器
class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}public String getIngredients() {return coffee.getIngredients() + ", Milk";}public double getPrice() {return coffee.getPrice() + 0.5;}
}// 糖咖啡装饰器
class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}public String getIngredients() {return coffee.getIngredients() + ", Sugar";}public double getPrice() {return coffee.getPrice() + 0.3;}
}// 客户端代码
public class Client {public static void main(String[] args) {// 创建基础咖啡对象Coffee baseCoffee = new SimpleCoffee();System.out.println("基础咖啡: " + baseCoffee.getIngredients() + ", 价格: " + baseCoffee.getPrice());// 添加牛奶Coffee milkCoffee = new MilkDecorator(baseCoffee);System.out.println("加入牛奶: " + milkCoffee.getIngredients() + ", 价格: " + milkCoffee.getPrice());// 添加糖Coffee sugarCoffee = new SugarDecorator(milkCoffee);System.out.println("加入糖: " + sugarCoffee.getIngredients() + ", 价格: " + sugarCoffee.getPrice());}
}

在上述代码中,我们定义了一个咖啡接口(Coffee),以及一个基础咖啡类(SimpleCoffee)实现了这个接口。然后,我们创建了一个咖啡装饰器基类(CoffeeDecorator),它也实现了咖啡接口,并通过构造函数接收一个咖啡对象。接下来,我们创建了两个具体的装饰器类:牛奶装饰器(MilkDecorator)和糖装饰器(SugarDecorator),它们都继承自咖啡装饰器基类,并分别扩展了咖啡的配料和价格。

最后,在客户端代码中,我们实例化了一个基础咖啡对象,然后使用装饰器类将其包装,以便于在咖啡中添加牛奶和糖。我们可以通过调用装饰器对象的 getIngredients() 和 getPrice() 方法来获取装饰后的咖啡的配料和价格。

运行上述代码,您应该会得到以下输出结果:

基础咖啡: Coffee, 价格: 2.0
加入牛奶: Coffee, Milk, 价格: 2.5
加入糖: Coffee, Milk, Sugar, 价格: 2.8

这是因为我们创建了一个基础咖啡对象,并使用装饰器对象依次包装它,以扩展咖啡的配料和价格。

装饰器模式的具体应用

  1. Java IO:Java的输入输出流(IO)框架使用了装饰器模式。InputStream和OutputStream是抽象基类,而具体的输入输出流类如FileInputStream、ByteArrayInputStream等都是装饰器类的子类。这种设计允许对输入输出流进行递归式的装饰,以扩展其功能和行为。

  2. Spring框架:Spring框架中的AOP(面向切面编程)功能使用了装饰器模式。通过在运行时使用动态代理,它可以在方法调用前后插入额外的行为,如日志记录、性能监控等。

  3. Servlet过滤器:Java Servlet中的过滤器功能使用了装饰器模式。Servlet过滤器可以在请求到达Servlet之前或者响应返回给客户端之前,对请求和响应进行处理和修改。

  4. Guava库:Google的Guava库中的许多工具类和方法使用了装饰器模式。例如,Guava的Collections类提供了许多静态方法对集合进行装饰,如unmodifiableCollection、synchronizedCollection等。

总结

装饰器(Decorator)模式是一种结构型设计模式,它允许动态地将新功能添加到对象中,同时又不改变其结构。装饰器模式基于组合而非继承原则,通过递归和委托来创建具有新功能的对象。装饰器模式适用于需要在运行时扩展对象功能的情况,而不希望生成大量的子类。在实际开发中,我们可以利用装饰器模式来为现有的类或框架添加额外的功能,同时保持代码的灵活性和可维护性。

关注微信公众号:“小虎哥的技术博客”。我们会定期发布关于Java技术的详尽文章,让您能够深入了解该领域的各种技巧和方法,让我们一起成为更优秀的程序员👩‍💻👨‍💻!

相关文章:

Java设计模式之装饰器(Decorator)模式

装饰器(Decorator)设计模式允许动态地将新功能添加到对象中,同时又不改变其结构。 什么是装饰器模式 装饰器(Decorator)模式通过将对象进行包装,以扩展其功能,而不需要修改其原始类。装饰器模…...

element ui树组件render-content 树节点的内容区的渲染另一种方式

直接上代码吧,不用h的写法。 <el-tree :data"data" node-key"id" default-expand-all :expand-on-click-node"false" :props"defaultProps":render-content"renderContentTree" node-click"handleNodeClick"&g…...

html a标签换行显示

文章目录 用css display属性不用css&#xff0c;可以用<br>标签换行示例 用css display属性 可以使用CSS的display属性来实现多个a标签每行显示一个。 HTML代码&#xff1a; <div class"link-container"><a href"#">Link 1</a>…...

关于Redis-存Long取Integer类型转换错误的问题

背景 最近遇到了两个Redis相关的问题&#xff0c;趁着清明假期&#xff0c;梳理整理。 1.存入Long类型对象&#xff0c;在代码中使用Long类型接收&#xff0c;结果报类型转换错误。 2.String对象的反序列化问题&#xff0c;直接在Redis服务器上新增一个key-value&#xff0c…...

设计模式一:简单工厂模式(Simple Factory Pattern)

简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一个通用的接口来创建各种不同类型的对象&#xff0c;而无需直接暴露对象的创建逻辑给客户端。 简单工厂的三个重要角色&#xff1a; 工厂类&#xff08;Factory Class&…...

如何利用plotly和geopandas根据美国邮政编码(Zip-Code)绘制美国地图

对于我自己来说&#xff0c;该需求源自于分析Movielens-1m数据集的用户数据&#xff1a; UserID::Gender::Age::Occupation::Zip-code 1::F::1::10::48067 2::M::56::16::70072 3::M::25::15::55117 4::M::45::7::02460 5::M::25::20::55455 6::F::50::9::55117我希望根据Zip-…...

ceph集群搭建

文章目录 理论知识具体操作搭建ceph本地源yum源及ceph的安装配置NTP&#xff08;解决时间同步问题&#xff09;部署ceph自定义crush 理论知识 Ceph是一个分布式存储系统&#xff0c;并且提供了文件、对象、块存储功能。 Ceph集群中重要的守护进程有&#xff1a;Ceph OSD、Cep…...

前端密码加密 —— bcrypt、MD5、SHA-256、盐

&#x1f414; 前期回顾悄悄告诉你&#xff1a;前端如何获取本机IP&#xff0c;轻松一步开启网络探秘之旅_彩色之外的博客-CSDN博客前端获取 本机 IP 教程https://blog.csdn.net/m0_57904695/article/details/131855907?spm1001.2014.3001.5501 在前端密码加密方案中&#xff…...

汽车UDS诊断深度学习专栏

1.英文术语 英文术语翻译Diagnostic诊断Onboard Diagnostic 在线诊断 Offboard Diagnostic离线诊断Unified diagnostic service简称 UDS 2.缩写表 缩写解释ISO国际标准化组织UDSUnified diagnostic service&#xff0c;统一的诊断服务ECU电控单元DTC 诊断故障码 ISO14229UD…...

macOS 下安装brew、nvm

1、brew&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" brew -v 查看版本 示例&#xff1a; 安装jdk brew search jdk 查询可用的jdk版本 brew install openjdk11 安装制定版本jdk 更换源&#xff1…...

【云原生】Kubernetes工作负载-StatefulSet

StatefulSet StatefulSet 是用来管理有状态应用的工作负载 API 对象 StatefulSet 用来管理某 Pod 集合的部署和扩缩&#xff0c; 并为这些 Pod 提供持久存储和持久标识符 和 Deployment 类似&#xff0c; StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同…...

Java:方法的重载

方法重载 为什么需要方法重载 在使用方法的过程中我们可能会遇到以下如同例子的情形&#xff1a; ​ ​ public class method1 {public static void main(String[] args) {int a1 10;int b1 20;double ret1 add(a1, b1);System.out.println("ret1 " ret1);do…...

7.react useCallback与useMemo函数使用与常见问题

react useCallback与useMemo函数使用与常见问题 useCallback返回一个可记忆的函数&#xff0c;useMemo返回一个可记忆的值&#xff0c;useCallback只是useMemo的一种特殊形式。 那么这到底是什么意思呢&#xff1f;实际上我们在父子通信的时候&#xff0c;有可能传递的值是一…...

Sentinel限流中间件

目录 介绍 Sentinel 的特征 Sentinel 的组成 实战使用 简单实例 配置本地控制台 使用可视化ui配置简单流控 配置异步任务限流 使用注解定义限流资源 SpringCloud整合Sentinel 简单整合 并发线程流控 关联模式 整合openFeign使用 介绍 随着微服务的流行&#xff0…...

使用ajax进行前后端交互的方法

使用ajax进行前后端交互的方法&#xff1a;&#xff08;我只测试通了json对象作为参数的方式&#xff0c;其他方式我没有测试通过&#xff09; 1、前端方法&#xff1a; 传参方式&#xff1a;POST 请求类型&#xff1a;json对象 响应类型&#xff1a;json对象 function test() …...

动手学深度学习——线性回归从零开始

生成数据集synthetic_data()读取数据集data_iter()初始化模型参数w, b定义模型&#xff1a;线性回归模型linreg()定义损失函数&#xff1a;均方损失squared_loss()定义优化算法&#xff1a;梯度下降sgd()进行训练&#xff1a;输出损失loss和估计误差 %matplotlib inline impor…...

Redis缓存击穿

Redis缓存击穿是指在使用Redis作为缓存时&#xff0c;某个热点数据过期或不存在&#xff0c;导致大量请求直接打到后端存储系统&#xff08;例如数据库&#xff09;&#xff0c;使得后端系统压力骤增&#xff0c;性能下降的情况。这种情况通常发生在热点数据失效的瞬间。 缓存…...

网络安全(黑客)自学的一些建议

1.选择方向 首先是选择方向的问题&#xff0c;网络安全是一个很宽泛的专业&#xff0c;包含的方向特别多。比如 web安全&#xff0c;系统安全&#xff0c;无线安全 &#xff0c;二进制安全&#xff0c;运维安全&#xff0c;渗透测试&#xff0c;软件安全&#xff0c;IOT安全&a…...

全志F1C200S嵌入式驱动开发(基于usb otg的spi-nor镜像烧入)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面既然已经搞定了spi-nor驱动,那么下一步考虑的就是怎么从spi-nor flash上面加载uboot、kernel和rootfs。目前spi-nor就是一块白片,上面肯定什么都没有,那么这个时候,我们要做…...

如何恢复损坏/删除的 Word 文件

有关如何修复不可读的 Microsoft Word 文件或 Rich Text 文件中的文本的分步说明。这些说明有助于从损坏的*.doc、*.docx、*.dot、*.dotx、*.rtf文件&#xff08;任何版本和大小&#xff09;中提取文本&#xff0c;只需单击几下&#xff1a; 从此处下载奇客数据恢复 &#xff…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...