当前位置: 首页 > 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…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...