面向对象设计模式:结构型模式之装饰器模式
文章目录
- 一、引入
- 二、装饰器模式
- 2.1 Intent 意图
- 2.2 Applicability 适用性
- 2.3 类图
- 2.4 优缺点
- 2.5 应用实例:Java IO 类
- 2.6 应用实例:咖啡馆订购系统
一、引入
-
咖啡馆订购系统
-
Initial 初始
- 4 种咖啡
- House blend (混合咖啡)
- Dark Roast (深度烘培)
- Decaf (低咖啡因咖啡)
- Espresso (意式浓缩咖啡)


- 4 种咖啡
-
需求变更:客户可以加料(咖啡、牛奶、糖等)
- steamed milk
- soy
- mocha
- Whip
使用继承:类爆炸 NO

修改父类:Beverage

需求倘若变更:料种类增加、料价格变化,需要修改 Beverage 类
Classes should be open for extension, but closed for modification:开放封闭原则,对修改封闭
No

Decorator…
二、装饰器模式
aka:Wrapper (包装器)
2.1 Intent 意图
- Attach additional responsibilities to an object dynamically. 可动态地将其他职责附加到对象上.
- Decorators provide a flexible alternative to subclassing for extending functionality. 装饰器为扩展功能提供了一种替代子类化的灵活替代方案.
- Dynamically extension
- Better than inheritance
2.2 Applicability 适用性
- To add responsibilities to individual objects dynamically without affecting other object.
- When extension by subclassing is impractical. 当子类化扩展是不切实际的.
- 如,子类数量爆炸
2.3 类图

- Component: defines the interface for objects that can have responsibilities added to them dynamically. 为可以动态地添加职责的对象定义接口
- ConcreteComponent: defines an object to which additional responsibilities can be attached. 定义一个可以附加其他责任的对象.
- Decorator: maintains a reference to a Component object and defines an interface that conforms to Component’s interface. 维护对 Component 对象的引用,并定义一个符合 Component 接口的接口
- ConcreteDecorator: adds responsibilities to the component. 向组件添加职责
2.4 优缺点
- 优点
- More flexibility than static inheritance. 比静态继承更灵活
- With Decorators, responsibilities can be added and removed at runtime simply by attaching and detaching them.
- 避免"类爆炸"
- 通过排列和组合,可以创建许多行为组合
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能
- More flexibility than static inheritance. 比静态继承更灵活
- 缺点
- Lots of little objects
- A decorator and its component are not same
- 多层装饰比较复杂
2.5 应用实例:Java IO 类
InputStream and OutputStream 字节流
Reader and Writer 字符流

FilterInputStream:protected volatile InputStream in;

FilterInputStream 与 InputStream 为组合和被组合关系
与装饰器设计模式类图相符!

public class JavaIO {public static void main(String[] args) throws FileNotFoundException {// Open an InputStream.FileInputStream in = new FileInputStream("test.dat");// Create a buffered InputStream.BufferedInputStream bin = new BufferedInputStream(in);// Create a buffered, data InputStream.DataInputStream dbin = new DataInputStream(bin);// Create an unbuffered, data InputStream.DataInputStream din = new DataInputStream(in);// Create a buffered, pushback, data InputStream.PushbackInputStream pbdbin = new PushbackInputStream(dbin);}
}
2.6 应用实例:咖啡馆订购系统
- 饮品抽象类:Beverage
public abstract class Beverage {protected String description = "Unknown Beverage";public String getDescription() {return description;}public abstract double cost();
}
- 咖啡类:继承 Beverage
public class DarkRoast extends Beverage {public DarkRoast() {description = "DarkRoast";}public double cost() {return .99;}
}
public class Espresso extends Beverage {public Espresso() {description = "Espresso";}public double cost() {return 1.99;}
}
public class HouseBlend extends Beverage {public HouseBlend() {description = "House Blend Coffee";}public double cost() {return .89;}
}
- 装饰器:CondimentDecorator
public abstract class CondimentDecorator extends Beverage {public abstract String getDescription();
}
- 装饰器子类:ConcreteDecorator
public class Mocha extends CondimentDecorator {Beverage beverage;public Mocha(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + ", Mocha";}public double cost() {return .20 + beverage.cost();}
}
public class Soy extends CondimentDecorator {Beverage beverage;public Soy(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + ", Soy";}public double cost() {return .15 + beverage.cost();}
}
public class Whip extends CondimentDecorator {Beverage beverage;public Whip(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + ", Whip";}public double cost() {return .10 + beverage.cost();}
}
- 使用与测试:
public class StarbuzzCoffee {public static void main(String[] args) {Beverage beverage = new Espresso();System.out.println(beverage.getDescription() + " $" + beverage.cost());Beverage beverage2 = new DarkRoast();beverage2 = new Mocha(beverage2);beverage2 = new Mocha(beverage2);beverage2 = new Whip(beverage2);System.out.println(beverage2.getDescription() + " $" + beverage2.cost());Beverage beverage3 = new HouseBlend();beverage3 = new Soy(beverage3);beverage3 = new Mocha(beverage3);beverage3 = new Whip(beverage3);System.out.println(beverage3.getDescription() + " $" + beverage3.cost());}
}

相关文章:
面向对象设计模式:结构型模式之装饰器模式
文章目录一、引入二、装饰器模式2.1 Intent 意图2.2 Applicability 适用性2.3 类图2.4 优缺点2.5 应用实例:Java IO 类2.6 应用实例:咖啡馆订购系统一、引入 咖啡馆订购系统 Initial 初始 4 种咖啡 House blend (混合咖啡)Dark Roast (深度烘培)Decaf (…...
Unity iOS 无服务器做一个排行榜 GameCenter
排行榜需求解决方案一(嗯目前只有一)UnityEngine.SocialPlatformsiOS GameCenterAppStoreConnect配置Unity 调用(如果使用GameCenter系统的面板,看到这里就可以了)坑(需要获取数据做自定义面板的看这里)iOS代码Unity 代码吐槽需求 需求:接入…...
现在招个会自动化测试的人是真难呀~你会个锤子的自动化测试
现在招个会自动化测试的人是真难呀~ 前一段时间公司计划要招2个自动化测试到岗,同事面试了十几个来应聘的人,发现一个很奇怪的现象,在面试的时候,如果问的是框架API、脚本编写这些问题,基本上所有人都能对答如流&…...
OracleDatabase——数据库表空间dmp导出与导入
由于公司的程序一直部署在客户现场内网,内网调试难度高,一般是有备份还原数据库的需求,这里简记备份(导出)数据库dmp文件与恢复(导入)的步骤。 一、导出dmp文件 exp与expdp命令异同 相同点&a…...
20张图带你彻底了解ReentrantLock加锁解锁的原理
哈喽大家好,我是阿Q。 最近是上班忙项目,下班带娃,忙的不可开交,连摸鱼的时间都没有了。今天趁假期用图解的方式从源码角度给大家说一下ReentrantLock加锁解锁的全过程。系好安全带,发车了。 简单使用 在聊它的源码…...
Dockerfile构建Springboot镜像
Dockerfile构建Springboot镜像 文章目录 Dockerfile构建Springboot镜像 简介实例演示 前期准备 Docker环境Springboot项目Dockerfile文件 Windows 要求构建镜像启动测试 Linux 要求构建镜像启动测试 简介 容器技术大流行的时代,也是docker大流行的时代。 此文…...
从深分页查询到覆盖索引
最近看到一道面试题,如何优化深分页查询 最简单的例子是 select * from web_bill_main limit 30000,10;分页达到30000行,需要把前面29999行都过滤掉,才能找到这10条数据 所以整体时间花了80ms(工具显示时间) 我当时的第一反应是࿰…...
Go语言学习的第三天--下部分(Gin框架的基础了解)
每天都会分享Go的知识,喜欢的朋友关注一下。每天的学习分成两部分基础(必要的,基础不牢地动山摇),另一部分是Go的一些框架知识(会不定时发布,因为小Wei也是一名搬砖人)。但是可以保证…...
JDK的动态代理(powernode 文档)(内含源代码)
JDK的动态代理(powernode 文档)(内含源代码) 源代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87546086 一、动态代理 目录JDK的动态代理(powernode 文档)࿰…...
第1章 多线程基础
第1章 多线程基础 1.1.2 线程与进程的关系 进程可以看成是线程的容器,而线程又可以看成是进程中的执行路径。 1.2 多线程启动 线程有两种启动方式:实现Runnable接口;继承Thread类并重写run()方法。 执行进程中的任务时才会产生线程&a…...
Linux基本指令(一)
文章目录文件操作文档操作系统管理网络通信备份压缩Ctrl Alt T 打开终端 文件操作 1.复制文件 cp afile bfile (将名为afile的文件复制到名为bfile的文件夹中,如果bfile文件不存在,系统将会创建此文件,如果bfile文件已经存在&a…...
el-dialog子组件在mounted周期内获取不到dom?
el-dialog子组件在mounted周期内获取不到dom?一、问题描述二、分析原因三、猜测正常父子组件在mounted生命周期内可以获得dom 父created—子created—子mounted—父mounted----子updated—父updated 一、问题描述 ** el-dialog控制显示隐藏是css控制的display&…...
第九章 opengl之光照(光照贴图)
OpenGL光照贴图漫反射贴图镜面光贴图光照贴图 一个物体的不同部分是不同的材质,那么会有不同的环境光和漫反射颜色表现。 漫反射贴图 原理就是:纹理。 是对同样的原理使用了不同的名字:其实都是使用一张覆盖物体的图像,让我们能…...
JDK动态代理(powernode CD2207 video)(内含教学视频+源代码)
JDK动态代理(powernode CD2207 video)(内含教学视频源代码) 教学视频原代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87545977 目录JDK动态代理(powernode CD2207 video…...
【Linux】Sudo的隐晦bug引发的一次业务问题排查
Sudo的隐晦bug引发的一次业务问题排查写在前面问题描述问题排查高负载现象排查日志排查跟踪任务调度过程Sudo引发的问题手动复现问题分析处理方案写在前面 记录一次生产环境sudo启动进程频繁被Kill且不报错的异常处理过程,如果遇到同样的问题只想要解决方案&#x…...
Java VisualVM 安装 Visual GC 插件图文教程
文章目录1. 通过运行打开 Java VisualVM 监控工具2. 菜单栏初始视图说明3. 工具插件菜单说明4. 手工安装插件5. 重启监控工具查看 Visual GC1. 通过运行打开 Java VisualVM 监控工具 首先确保已安装 Java 环境,如此处安装版本 JDK 1.8.0_161 C:\Users\niaonao>j…...
【C语言】详解静态变量static
关键字static 在C语言中:static是用来修饰变量和函数的static主要作用为:1. 修饰局部变量-静态局部变量 2. 修饰全局变量-静态全局变量3. 修饰函数-静态函数在讲解静态变量之前,我们应该了解静态变量和其他变量的区别: 修饰局部变量 //代码1 #include &l…...
SpringBoot整合ElasticSearch实现模糊查询,排序,分页,高亮
目录 前言 1.框架集成-SpringData-整体介绍 1.1Spring Data Elasticsearch 介绍 2.框架集成Spring Data Elasticsearch 2.1版本说明 2.2.idea创建一个springboot项目 2.3.导入依懒 2.3.增加配置文件 2.4Spring Boot 主程序。 2.5.数据实体类 2.6.配置类 2.7.DAO 数据…...
YARN基本架构
主要由ResourceManager、NodeManager、ApplicationMaster和Container等组件构成,如图所YA示。 ResourceManager(RM) RM是全局资源管理器,负责整个系统的资源管理和分配 主要由两个组件构成:Scheduler调度器和应用程序…...
【C++复习】类和对象全知识点总结
类和对象写在前面类和对象面向对象类类的定义类的访问限定符类的作用域类的实例化类对象大小this指针类的默认成员函数构造函数析构函数拷贝构造函数运算符重载赋值运算符重载前置后置重载取地址及const取地址操作符重载const 成员static 成员友元友元函数有元类内部类匿名对象…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
