设计模式篇(Java):装饰者模式
👨💻本文专栏:设计模式篇-装饰者模式
👨💻本文简述:装饰者模式的详解以及jdk中的应用
👨💻上一篇文章: 设计模式篇(Java):桥接模式
👨💻有任何问题,都可以私聊我,文章最后有vx名片。感谢支持!
🦹知道的越多,不知道的越多!!!不能停下学习的脚步
十、装饰者模式
10.1 装饰者模式基本介绍
引出装饰者模式的示例
咖啡吧订单问题:
- 咖啡种类/单品咖啡:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式 咖啡)、Decaf(无因咖啡)
- 调料:Milk、Soy(豆浆)、Chocolate
- 要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
- 使用OO的来计算不同种类咖啡的费用: 客户可以点单品咖啡,也可以单品咖啡+调料组合
那么使用传统方法(最笨的)
问题分析
- Drink 是一个抽象类,表示饮料
- des就是对咖啡的描述, 比如咖啡的名字
- cost() 方法就是计算费用,Drink 类中做成一个抽象方法
- Decaf 就是单品咖啡, 继承Drink, 并实现cost
- Espress && Milk 就是单品咖啡+调料, 这个组合很多
- 问题:这样设计,会有很多类,当我们增加一个单品咖啡,或者一个新的调料, 类的数量就会倍增,就会出现类爆炸
优化方法一
前面分析到方案1因为咖啡单品+调料 组合会造成类的倍增,因此可以做改进,将调料内置到Drink类,这样就不会造成类数量过多。从而提高项目的维护性。
问题分析:
- 有效的缓解了类爆炸的问题
- 但是在扩展的时候(新增或修改配料的时候)代码维护量过大,不仅要新增类,还需要修改drink
优化方法二:装饰者模式
装饰者模式定义
- 装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
装饰者模式原理
- 装饰者模式就像打包一个快递
- 主体:比如:陶瓷、衣服 (Component) // 被装饰者
- 包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)
-
Component 主体:比如类似前面的Drink
-
ConcreteComponent和Decorator
- ConcreteComponent:具体的主体, 比如前面的各个单品咖啡
- Decorator: 装饰者,比如各调料
-
在如图的Component与ConcreteComponent之间,如果 ConcreteComponent类很多,还可以设计一个缓冲层,将共有的部分提取出来, 抽象层一个类
10.2 装饰者模式解决需求
使用装饰者模式设计的方案
说明:
- Drink 类就是前面说的抽象类, Component
- ACoffee 就单品咖啡
- Decorator 是一个装饰类,含有一个被装饰的对象(Drink obj)
- Decorator 的cost 方法进行一个费用的叠加计算,递归的计算价格
代码示例
Drink类
/*** Drink类就是抽象的被装饰者,给具体的装饰者和被修饰者继承* @author cVzhanshi* @create 2023-09-05 15:16*/
@Data
public abstract class Drink {// 描述private String des;// 价格private float price = 0.0f;// 计算费用的抽象方法// 子类来实现public abstract float cost();
}
Coffee类(缓冲层)
/*** 缓冲层* @author cVzhanshi* @create 2023-09-05 15:32*/
public class Coffee extends Drink {@Overridepublic float cost() {return super.getPrice();}
}
具体的被装饰者——各种咖啡
/*** @author cVzhanshi* @create 2023-09-05 15:33*/
public class BCoffee extends Coffee {public BCoffee() {setDes("BCoffee");setPrice(3.0f);}
}/*** @author cVzhanshi* @create 2023-09-05 15:33*/
public class ACoffee extends Coffee {public ACoffee() {setDes("ACoffee");setPrice(5.0f);}
}
Decorator装饰类
/*** Decorator 是一个装饰类,含有一个被装饰的对象(Drink obj)* @author cVzhanshi* @create 2023-09-05 15:59*/
public class Decorator extends Drink{private Drink coffee;public Decorator(Drink coffee) {this.coffee = coffee;}@Overridepublic float cost() {// 调料的价格 + coffee的总价格return coffee.cost() + super.getPrice();}@Overridepublic String getDes() {return super.getDes() + " || " + coffee.getDes();}
}
具体的装饰类
/*** @author cVzhanshi* @create 2023-09-05 16:09*/
public class Milk extends Decorator {public Milk(Drink coffee) {super(coffee);setPrice(1.0f);setDes(" 牛奶 ");}
}/*** @author cVzhanshi* @create 2023-09-05 16:10*/
public class Soy extends Decorator {public Soy(Drink coffee) {super(coffee);setDes(" 糖 ");setPrice(9.0f);}
}
制作咖啡(允许效果)
/*** @author cVzhanshi* @create 2023-09-05 16:11*/
public class CoffeeBar {public static void main(String[] args) {// 装饰者模式下订一份A咖啡 + 一份糖 + 两份牛奶// 1、点一份a咖啡Drink aCoffee = new ACoffee();System.out.println("费用1 = " + aCoffee.cost());System.out.println("描述 = " + aCoffee.getDes());// 2、a咖啡加入一份糖aCoffee = new Soy(aCoffee);System.out.println("aCoffee 加入一份糖 费用 = " + aCoffee.cost());System.out.println("aCoffee 加入一份糖 描述 = " + aCoffee.getDes());//2、再加入两份份牛奶aCoffee = new Milk(aCoffee);System.out.println("aCoffee 加入一份糖 一份牛奶 费用 = " + aCoffee.cost());System.out.println("aCoffee 加入一份糖 一份牛奶 描述 = " + aCoffee.getDes());aCoffee = new Milk(aCoffee);System.out.println("aCoffee 加入一份糖 两份牛奶 费用 = " + aCoffee.cost());System.out.println("aCoffee 加入一份糖 两份牛奶 描述 = " + aCoffee.getDes());}
}// 允许效果
// 费用1 = 5.0
// 描述 = ACoffee
// aCoffee 加入一份糖 费用 = 14.0
// aCoffee 加入一份糖 描述 = 糖 || ACoffee
// aCoffee 加入一份糖 一份牛奶 费用 = 15.0
// aCoffee 加入一份糖 一份牛奶 描述 = 牛奶 || 糖 || ACoffee
// aCoffee 加入一份糖 两份牛奶 费用 = 16.0
// aCoffee 加入一份糖 两份牛奶 描述 = 牛奶 || 牛奶 || 糖 || ACoffee
10.3 装饰者模式在JDK中的应用
通过阅读源码可知jdk中的io结构就是一个很典型的装饰者模式
结构如下:
- InputStream 是抽象类,类似我们前面讲的 Drink
public abstract class InputStream implements Closeable {// ....
}
-
FilelnputStrearm 是 InputStream 子类,是具体的被装饰者类似我们前面的ACoffee、BCofee
-
FilterInputStream 是InputStream 子类:类似我们前面的 Decorator 修饰者
public class FilterInputStream extends InputStream {/**FilterinputStream 类有 protected volatile InputStream in;即含被装饰者 * The input stream to be filtered.*/protected volatile InputStream in;// ...}
- DatalnputStream 是 FilterinputStrcam 子类,具体的修饰者,类似前面的 Milk,Soy 等
相关文章:
设计模式篇(Java):装饰者模式
👨💻本文专栏:设计模式篇-装饰者模式 👨💻本文简述:装饰者模式的详解以及jdk中的应用 👨💻上一篇文章: 设计模式篇(Java):桥接模式 👨&am…...
Spark【RDD编程(三)键值对RDD】
简介 键值对 RDD 就是每个RDD的元素都是 (key,value)类型的键值对,是一种常见的 RDD,可以应用于很多场景。 因为毕竟通过我们之前Hadoop的学习中,我们就可以看到对数据的处理,基本都是以…...
从板凳围观到玩转行家:Moonbeam投票委托如何让普通用户一同参与
今年5月,Moonbeam发起了一项社区链上治理中投票委托反馈的调查。187位社区成员参与了这项调查,调查发现受访者对治理感兴趣,增加参与度只需要进行一些调整,即更简化的投票流程。 治理和去中心化是Web3的核心,随着Moon…...
SpringMVC的文件上传文件下载多文件上传---详细介绍
目录 前言: 一,文件上传 1.1 添加依赖 1.2 配置文件上传解析器 1.3 表单设置 1.4 文件上传的实现 二,文件下载 controller层 前端jsp 三,多文件上传 Controller层 运行 前言: Spring MVC 是一个基于 Java …...
Spark【RDD编程(四)综合案例】
案例1-TOP N个数据的值 输入数据: 1,1768,50,155 2,1218,600,211 3,2239,788,242 4,3101,28,599 5,4899,290,129 6,3110,54,1201 7,4436,259,877 8,2369,7890,27 处理代码: def main(args: Array[String]): Unit {//创建SparkContext对象val conf…...
Golang报错mixture of field:value and value initializers
Golang报错mixture of field:value and value initializers 这个错误跟编程习惯(模式)有关,都知道golang 语言的编程与java /python 以及其他的编程语言相似 ,一通百通,易学万卷书。 编程中同一个结构中要保持唯一模…...
【网络教程】记一次使用Docker手动搭建BT宝塔面板的全过程(包含问题解决如:宝塔面板无法开启防火墙,ssh,nginx等)
文章目录 准备安装安装宝塔面板开启ssh和修改ssh的密码导出镜像问题解决宝塔面板无法开启防火墙无法启动ssh设置密码nginx安装失败设置开机启动相关服务准备 演示的系统环境:Ubuntu 22.04.3 LTS更新安装/升级docker到最新版本升级docker相关命令如下# 更新软件包列表并自动升级…...
【大虾送书第九期】速学Linux:系统应用从入门到精通
目录 🍭写在前面 🍭为什么学习Linux系统 🍭Linux系统的应用领域 🍬1.Linux在服务器的应用 🍬2.嵌入式Linux的应用 🍬3.桌面Linux的应用 🍭Linux的版本选择 &a…...
docker相关命令
####### 帮助启动类命令 ########## 启动docker systemctl start docker 停止docker systemctl stop docker 重启docker systemctl restart docker 查看docker状态 systemctl status docker 开机启动 systemctl enable docker 查看docker概要信息 docker info 查看…...
【Redis】4、rsync远程同步
与inodify结合使用,实现实时同步 rsync简介 rsync(Remote Sync,远程同步)是一个开源的快速备份工具,可以在不同主机之间镜像同步整个目录树,;支持增量备份,并保持链接和权限&#…...
无服务架构--Serverless
无服务架构 无服务架构(Serverless Architecture)即无服务器架构,也被称为函数即服务(Function as a Service,FaaS),是一种云计算模型,用于构建和部署应用程序,无需关心…...
2023-09-07 LeetCode每日一题(修车的最少时间)
2023-09-07每日一题 一、题目编号 2594. 修车的最少时间二、题目链接 点击跳转到题目位置 三、题目描述 给你一个整数数组 ranks ,表示一些机械工的 能力值 。ranksi 是第 i 位机械工的能力值。能力值为 r 的机械工可以在 r * n2 分钟内修好 n 辆车。 同时给你…...
数据挖掘实验-主成分分析与类特征化
数据集&代码https://www.aliyundrive.com/s/ibeJivEcqhm 一.主成分分析 1.实验目的 了解主成分分析的目的,内容以及流程。 掌握主成分分析,能够进行编程实现。 2.实验原理 主成分分析的目的 主成分分析就是把原有的多个指标转化成少数几个代表…...
70. 爬楼梯 (进阶),322. 零钱兑换,279.完全平方数
代码随想录训练营第45天|70. 爬楼梯 (进阶,322. 零钱兑换,279.完全平方数 70.爬楼梯文章思路代码 322.零钱兑换文章思路代码 279.完全平方数文章思路代码 总结 70.爬楼梯 文章 代码随想录|0070.爬楼梯完全背包版本 思路 将楼梯长度视为背…...
Apache Doris 2.0 如何实现导入性能提升 2-8 倍
数据导入吞吐是 OLAP 系统性能的重要衡量标准之一,高效的数据导入能力能够加速数据实时处理和分析的效率。随着 Apache Doris 用户规模的不断扩大, 越来越多用户对数据导入提出更高的要求,这也为 Apache Doris 的数据导入能力带来了更大的挑战…...
RabbitMQ: topic 结构
生产者 package com.qf.mq2302.topic;import com.qf.mq2302.utils.MQUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection;public class Pubisher {public static final String EXCHANGE_NAME"mypubilisher";public static void ma…...
信息系统项目管理教程(第4版):第二章 信息技术及其发展
请点击↑关注、收藏,本博客免费为你获取精彩知识分享!有惊喜哟!! 第二章 信息技术及其发展 2.1信息技术及其发展 信息技术是以微电子学为基础的计算机技术和电信技术的结合而形成的,对声音的、图像的、文字的、数字…...
有哪些适合初学者的编程语言?
C语言 那为什么我还要教你C语言呢?因为我想要让你成为一个更好、更强大的程序员。如果你要变得更好,C语言是一个极佳的选择,其原因有二。首先,C语言缺乏任何现代的安全功能,这意味着你必须更为警惕,时刻了…...
uni-app动态tabBar,根据不同用户展示不同的tabBar
1.uni框架的api实现 因为我们用的是uni-app框架开发,所以在创建项目的时候直接创建uni-ui的项目即可,这个项目模板中自带了uni的一些好用的组件和api。 起初我想着这个效果不难实现,因为官方也有api可以直接使用,所以我最开始尝试…...
手写Spring:第6章-资源加载器解析文件注册对象
文章目录 一、目标:资源加载器解析文件注册对象二、设计:资源加载器解析文件注册对象三、实现:资源加载器解析文件注册对象3.1 工程结构3.2 资源加载器解析文件注册对象类图3.3 类工具类3.4 资源加载接口定义和实现3.4.1 定义资源加载接口3.4…...
Redis 7 第八讲 集群模式(cluster)架构篇
集群架构 Redis 集群架构图 集群定义 Redis 集群是一个提供在多个Redis节点间共享数据的程序集;Redis集群可以支持多个master 应用场景 Redis集群支持多个master,每个master又可以挂载多个slave读写分离支持数据的高可用支持海量数据的读写存储操作集群自带Sentinel的故障…...
【PowerQuery】导入与加载XML
在标准数据格式类型里面,有一类比较特殊的数据类型,就是层次结构数据。层次结构数据和标准的结构型数据方式完全不同,在实际应用过程中使用最为频繁的几种数据类型如下。 XML数据格式Json 数据格式Yaml 数据格式我们将在本节和大家一起分享下XML格式数据集成,下一节和大家分…...
vue 预览视频
1.预览本地文件 1.1 直接给video或者embed的src赋值本地路径 <video :src"videoUrl"></video> // 或者 使用embed标签<embed :src"videoUrl" /> 1.2 读取文件流形式 <input type"file" ref"file" /> <vi…...
4个维度讲透ChatGPT技术原理,揭开ChatGPT神秘技术黑盒!(文末送书)
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
【无标题】@Scheduled 的cron
, :指定多个值。 -:表示一个区间。 / :指定一个值的增加幅度。n/m表示从n开始,每次增加m。 L:是last的缩写,表示最后一天,用在日表示一个月中的最后一天,用在周表示每周最后一天&…...
IP和MAC的作用区别
在 IP 地址的上一行是 link/ether fa:16:3e:c7:79:75 brd ff:ff:ff:ff:ff:ff,这个被称为 MAC 地址,是一个网卡的物理地址,用十六进制,6 个 byte 表示。 一个网络包要从一个地方传到另一个地方,除了要有确定的地址&…...
python趣味编程-数独游戏
数独游戏是一个用Python编程语言编写的应用程序。该项目包含可以显示实际应用程序的基本功能。该项目可以让修读 IT 相关课程并希望开发简单应用程序的学生受益。这个Python 数独游戏是一个简单的项目,可用于学习tkinter库的实践。这个数独游戏可以提供Python编程的基本编码技…...
MySQL/MariaDB 查询某个 / 多个字段重复数据
创建测试表和数据 # 创建表 create table if not exists t_duplicate (name varchar(255) not null,age int not null );# 插入测试数据 insert into t_duplicate(name, age) values(a, 1); insert into t_duplicate(name, age) values(a, 2);查询单个字段重复 使用 count() …...
【力扣每日一题】2023.9.10 课程表Ⅱ
目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 今天的题目和昨天类似,不过今天要我们求出学习所有课程的先后顺序。 昨天只需要我们求出能否学习完所有课程,因此…...
VSCODE CMAKE C++ 工程调试, C++不以科学计数法输出并控制小数位数
1. VSCODE调试CMAKE工程配置1.1 修改CMakeLists.txt文件1.2. 程序中1.3. launch.json配置1.4 开始调试1.5 注意 2. C设置输出浮点数且保留位数固定 1. VSCODE调试CMAKE工程配置 1.1 修改CMakeLists.txt文件 加这一句 set(CMAKE_BUILD_TYPE "Debug")1.2. 程序中 在…...
网络培训法/seo外链推广工具下载
原标题:一加6T被曝将预装Android P 这一点其它品牌比不了近年来国产手机群雄崛起,不仅在国内获得了很高的呼声,一些品牌在国外也拥有着很高的热度,从以往的三星、苹果手中抢占了很多的份额,如今三星在国内的销量非常惨…...
wordpress 秀米/深圳seo公司排名
首先我们打开引擎,引擎窗口——文件——新建——55ide客户端——新建一个工程 一般新建在引擎根目录下面的,游戏作品里面。当然,你要放到其他位置,也可以,谁叫你这么叼 这就是进入主程序的界面。 加载:初始…...
哪个网站做长图免费转高清图片/网页设计培训学校
日子一去不复返了HTML用于造型的网页。今天,CSS规则,很难想象没有它的任何网页设计。CSS在最近非常先进,用于创建复杂的Web设计和风格。那么,我们为什么要使用CSS框架?答案很简单。CSS框架主要包括预定义的书库&#x…...
热水器网站建设 中企动力/郴州网站推广
因为在前两个月的工作中,使用PPT的次数较多,所以这里准备继续写一下这个PPT2010的文章,不过之前通过标签搜索,我发现了两篇不错的介绍在PPT中插入视频的文章,这里给大家推荐一下,同时我这篇文章主要写一下那…...
装饰网站开发背景/成都比较靠谱的seo
打开下载的mysql安装文件mysql-5.0.27-win32.zip,双击解压缩,运行“setup.exe”,出现如下界面: mysql安装向导启动,按“Next”继续 选择安装类型,有“Typical(默认)”、“Complete&a…...
石家庄网站建设成功案例/软文推广有哪些平台
0. 其他处理 计时: tic net train(net, X, y); toc1. 一个简单的 demo(单层感知器) P [1, 1, 1, 1, 0, 0, 0, 0; 0, 0, 1, 1, 0, 1, 1, 0; 0, 1, 0, 1, 1, 0, 1, 0];% 每一列表示一个输入样本 T [-1, 1, 1, 1, -1, -1, 1, -1];% 表示输出值…...