【Java设计模式】八、装饰者模式
文章目录
- 0、背景
- 1、装饰者模式
- 2、案例
- 3、使用场景
- 4、源码中的实际应用
0、背景
有个快餐店,里面的快餐有炒饭FriedRice 和 炒面FriedNoodles,且加配菜后总价不一样,计算麻烦。如果单独使用继承,那就是:

类爆炸不说,再来个炒河粉,就发现这样写扩展性很差。
1、装饰者模式
指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。角色:
- 抽象构件:具体构件的规范接口
- 具体构件:被装饰(被增加功能)的原始对象
- 抽象装饰:继承抽象构件
- 具体装饰:实现抽象装饰,给具体构件对象添加功能
总之,用于动态扩展一个类的功能(增强目标对象),而非使用继承
2、案例

定义快餐类(抽象构件):
//快餐接口
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public abstract class FastFood {private float price;private String desc;public abstract float cost(); //获取价格
}
定义炒饭、炒面类(具体的构件)
//炒饭
public class FriedRice extends FastFood {public FriedRice() {super(10, "炒饭"); //调用父类的构造方法,给炒饭的价格和描述赋值,即一碗炒饭10元}public float cost() {return getPrice();}
}
//炒面
public class FriedNoodles extends FastFood {public FriedNoodles() {super(12, "炒面"); //调用父类的构造方法,给炒面的价格和描述赋值}public float cost() {return getPrice();}
}
定义装饰类,属于抽象装饰角色,实现或者继承抽象构件,并聚合它
//配料
public abstract class Garnish extends FastFood {private FastFood fastFood; //声明抽象构件的变量public FastFood getFastFood() {return fastFood;}public void setFastFood(FastFood fastFood) {this.fastFood = fastFood;}public Garnish(FastFood fastFood, float price, String desc) {super(price,desc);this.fastFood = fastFood;}
}
定义配料类(属于具体的装饰者角色),继承装饰者类:
//鸡蛋配料
public class Egg extends Garnish {public Egg(FastFood fastFood) { //给属性赋值super(fastFood,1,"鸡蛋"); //一个鸡蛋一块钱 + 一份快餐}@Overridepublic float cost() {return getPrice() + getFastFood().getPrice(); //鸡蛋的价格 + 快餐的价格}@Overridepublic String getDesc() {return super.getDesc() + getFastFood().getDesc();}
}
//培根配料
public class Bacon extends Garnish {public Bacon(FastFood fastFood) {super(fastFood,2,"培根"); //一个培根两块钱 + 一份快餐}@Overridepublic float cost() {return getPrice() + getFastFood().getPrice();}@Overridepublic String getDesc() {return super.getDesc() + getFastFood().getDesc();}
}
测试:
//测试类
public class Client {public static void main(String[] args) {//点一份炒饭FastFood food = new FriedRice();//花费的价格System.out.println(food.getDesc() + " " + food.cost() + "元");System.out.println("========");//点一份加鸡蛋的炒饭FastFood food1 = new FriedRice();food1 = new Egg(food1); 妙!//花费的价格System.out.println(food1.getDesc() + " " + food1.cost() + "元");System.out.println("========");//点一份加培根的炒面FastFood food2 = new FriedNoodles();food2 = new Bacon(food2); 妙!//花费的价格System.out.println(food2.getDesc() + " " + food2.cost() + "元");}
}
后续如果需求变动,要加一个新配料:火腿,那就定义一个类去继承Garnish类即可。且任何配料可以自由搭配任何主食(组合不同的装饰者对象),这比排列组合写出n个子类好多了。继承是静态的附加责任,装饰者则是动态的附加责任。
3、使用场景
不能采用继承的方式对已有功能进行扩充时,可用装饰者模式。比如:
- 类被final修饰,不能被继承
- 扩展项目太多,用继承会子类爆炸
- 某些功能需要支持动态添加和动态撤销
4、源码中的实际应用
JDK中BufferedWriter等包装类,用到了装饰者模式,对Writer类进行了增强
public class Demo {public static void main(String[] args) throws Exception{//创建BufferedWriter对象//创建FileWriter对象FileWriter fw = new FileWriter("C:\\Users\\Think\\Desktop\\a.txt");BufferedWriter bw = new BufferedWriter(fw);//写数据bw.write("hello Buffered");bw.close();}
}

相关文章:
【Java设计模式】八、装饰者模式
文章目录 0、背景1、装饰者模式2、案例3、使用场景4、源码中的实际应用 0、背景 有个快餐店,里面的快餐有炒饭FriedRice 和 炒面FriedNoodles,且加配菜后总价不一样,计算麻烦。如果单独使用继承,那就是: 类爆炸不说&a…...
python INI文件操作与configparser内置库
目录 INI文件 configparser内置库 类与方法 操作实例 导入INI 查询所有节的列表 判断某个节是否存在 查询某个节的所有键的列表 判断节下是否存在某个键 增加节点 删除节点 增加节点的键 修改键值 保存修改结果 获取键值 获取节点所有键值 INI文件 即Initiali…...
软考笔记--软件系统质量属性
一.软件系统质量属性的概念 软件系统的质量就是“软件系统与明确地和隐含的定义的需求相一致的程度”。更具体地说,软件系统质量就是软件与明确地叙述的功能和性能需求文档中明确描述的开发标准以及任何专业开发的软件产品都应该具有的隐含特征相一致的程度。从管理…...
新型设备巡检方案-手机云巡检
随着科技的不断发展,设备巡检工作也在逐步向智能化、高效化方向转变。传统的巡检方式往往需要人工逐个设备检查,耗时耗力,效率低下,同时还容易漏检和误检。而新型设备巡检应用—手机蓝牙云巡检的出现,则为设备巡检工作…...
node.js 下 mysql2 的 CURD 功能极简封装
此封装适合于使用 SQL 直接操作数据库的小型后端项目,更多功能请查阅MySQL2官网 // 代码保存到单独的 js 文件const mysql require(mysql2/promise)const debug true let conn/*** 执行 SQL 语句* param {String} sql* param {*} params* returns {Array}*/ const…...
Cloud-Eureka服务治理-Ribbon负载均衡
构建Cloud父工程 父工程只做依赖版本管理 不引入依赖 pom.xml <packaging>pom</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.9.RELEA…...
Northwestern University-844计算机科学与技术/软件工程-机试指南【考研复习】
本文提到的西北大学是位于密歇根湖泊畔的西北大学。西北大学(英语:Northwestern University,简称:NU)是美国的一所著名私立研究型大学。它由九人于1851年创立,目标是建立一所为西北领地地区的人服务的大学。…...
【Linux的网络编程】
1、OSI的七层网络模型有哪些,每一层有什么作用? 答:(1)应用层:负责处理不同应用程序之间的通信,需要满足提供的协议,确保数据发送方和接收方的正确。 (2)表…...
vue-seamless-scroll 点击事件不生效
问题:在使用此插件时发现,列表内容前几行还是能正常点击的,但是从第二次出现的列表开始就没有点击事件了 原因:因为html元素是复制出来的(滚动组件是将后面的复制出来一份,进行填铺页面,方便滚动…...
前端工程部署步骤小记
安装mqtt: “mqtt”: “^4.3.7”, npm install git panjiacheng 后台demo下载zip 1、npm install --registryhttps://registry.npmmirror.com 2、npm run dev 前端demo创建 1、安装npm 2、npm install vuenext 3、npm install -g vue/cli 查看版本 vue --version 4、更新插件…...
TS常见问题
文章目录 1. 什么是 TypeScript?它与 JavaScript 有什么区别?2. TS 泛型、接口、泛型工具record、Pick、Omit3. TS unknow和any的区别,如何告诉编译器unknow一定是某个类型?4. 元组与常规数组的区别5. 什么是泛型,有什么作用&…...
linux系统nginx常用命令
查nginx位置 find / -name nginx nginx目录:/usr/local/ 查看nginx进程号 ps -ef |grep nginx 停止进程 kill 2072 启动 ./sbin/nginx /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf 启动并校验校验配置文件 ./sbin/nginx -t 看到如下显…...
MySQl基础入门③
上一遍内容 接下来我们都使用navicat软件来操作数据了。 1.新建数据库 先创建我门自己的一个数据库 鼠标右键点击bendi那个绿色海豚的图标,然后选择新建数据库。 数据库名按自己喜好的填,不要写中文, 在 MySQL 8.0 中,最优的字…...
idea Gradle 控制台中文乱码
如下图所示,idea 中的 Gradle 控制台中文乱码: 解决方法,如下图所示: 注意:如果你的 idea 使用 crack 等方式破解了,那么你可能需要在文件 crack-2023\jetbra\vmoptions\idea.vmoptions 中进行配置…...
嵌入式学习day31 网络
网络: 数据传输,数据共享 1.网络协议模型: OSI协议模型 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式(数据报…...
Docker网络+原理+link+自定义网络
目录 一、理解Docker网络 1.1 运行tomcat容器 1.2 查看容器内部网络地址 1.3 测试连通性 二、原理 2.1 查看网卡信息 2.2 再启动一个容器测试网卡 2.3 测试tomcat01 和tomcat02是否可以ping通 2.4 只要删除容器,对应网桥一对就没了 2.5 结论 三、--link 3.…...
Effective C++ 学习笔记 条款16 成对使用new和delete时要采取相同形式
以下动作有什么错? std::string *stringArray new std::string[100]; // ... delete stringArray;每件事看起来都井然有序,使用了new,也搭配了对应的delete。但还是有某样东西完全错误:你的程序行为未定义。至少,str…...
PokéLLMon 源码解析(四)
.\PokeLLMon\poke_env\exceptions.py """ This module contains exceptions. """# 定义一个自定义异常类 ShowdownException,继承自内置异常类 Exception class ShowdownException(Exception):"""This exception is …...
区块链基础知识01
区块链:区块链技术是一种高级数据库机制,允许在企业网络中透明地共享信息。区块链数据库将数据存储在区块中,而数据库则一起链接到一个链条中。数据在时间上是一致的,在没有网络共识的情况下,不能删除或修改链条。 即&…...
YOLOv9(2):YOLOv9网络结构
1. 前言 本文仅以官方提供的yolov9.yaml来进行简要讲解。 讲解之前,还是要做一些简单的铺垫。 Slice层不做任何的操作,纯粹是做一个占位层。这样一来,在parse_model时,ch[n]可表示第n层的输出通道。 Detect和DDetect主要区别还…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
