JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能

作者主页:Designer 小郑
作者简介:3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN博客专家,阿里云社区专家博主,蓝桥云课讲师。

在这里插入图片描述

目录

  • 一、什么是装饰模式
  • 二、装饰模式实例
  • 三、装饰模式的应用场景
  • 四、装饰模式面试题


一、什么是装饰模式

装饰模式是一种设计模式,属于结构型模式之一。

在 Java 中,装饰模式通过动态地将责任附加到对象上,以扩展其功能,它提供了一种比继承更灵活的方式来扩展对象的功能。

在装饰模式中,有一个基础对象(被装饰对象)和一系列装饰器(装饰对象)。

装饰器和基础对象实现同一个接口,这样它们可以相互替换。

装饰器包含一个基础对象的引用,并将新的功能添加到基础对象上。

使用装饰模式,我们可以 在运行时动态地扩展对象的功能,而不需要修改已有的代码 \color{red}{在运行时动态地扩展对象的功能,而不需要修改已有的代码} 在运行时动态地扩展对象的功能,而不需要修改已有的代码,它将对象的行为和功能的扩展分离开来,使得代码更加灵活可扩展

下面是一个简单的Java代码示例,请同学们复制到本地执行。

// 定义口
public interface Shape {void draw();
}// 实现接口的基础对象
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("画一个圆形");}
}// 实现接口的装饰器
public abstract class ShapeDecorator implements Shape {protected Shape decoratedShape;ShapeDecorator(Shape decoratedShape) {this.decoratedShape = decoratedShape;}@Overridepublic void draw() {decoratedShape.draw();}
}// 具体的装饰器
public class RedShapeDecorator extends ShapeDecorator {public RedShapeDecorator(Shape decoratedShape) {super(decoratedShape);}@Overridepublic void draw() {decoratedShape.draw();setRedBorder();}private void setRedBorder() {System.out.println("添加红色边框");}
}// 使用示例
public class Main {public static void main(String[] args) {Shape circle = new Circle();// 使用装饰器功能扩展Shape redCircle = new RedShapeDecorator(new Circle());Shape redRectangle = new RedShapeDecorator(new Rectangle());circle.draw();          // 输出:画一个圆形redCircle.draw();       // 输出:画一个圆形,添加红色边框redRectangle.draw();    // 输出:画一个长方,添加红色边框}
}

在这个例子中,Circle是基础对象,ShapeDecorator是装饰器,RedShapeDecorator是具体的装饰器。

使用装饰器可以在运行时为基础对象添加新的功能,而不需要修改基础对象本的代码。

在这里插入图片描述


二、装饰模式实例

以下是一个简单的 Java 装饰模式的实例代码,请同学们复制到本地执行。

// 定义接口
interface Shape {void draw();
}// 实现接口的基础对象
class Circle implements Shape {@Overridepublic void draw() {System.out.println("画一个圆形");}
}// 实现接口的装饰器
abstract class ShapeDecorator implements Shape {protected Shape decoratedShape;public ShapeDecorator(Shape decoratedShape) {this.decoratedShape = decoratedShape;}@Overridepublic void draw() {decoratedShape.draw();}
}// 具体的装饰器
class RedShapeDecorator extends ShapeDecorator {public RedShapeDecorator(Shape decoratedShape) {super(decoratedShape);}@Overridepublic void draw() {decoratedShape.draw();setRedBorder();}private void setRedBorder() {System.out.println("添加红色边框");}
}// 使用示例
public class Main {public static void main(String[] args) {Shape circle = new Circle();// 使用装饰器功能扩展Shape redCircle = new RedShapeDecorator(new Circle());Shape redRectangle = new RedShapeDecorator(new Rectangle());circle.draw(); // 输出:画一个圆形redCircle.draw(); // 输出:画一个圆形,添加红色边框redRectangle.draw(); // 输出:画一个长方形,添加红色边框}
}

在这个例子中,Circle是基础对象,ShapeDecorator是装饰器,RedShapeDecorator是具体的装饰器。

使用装饰器可以在运行时为基础对象添加新的功能,而不需要修改基础对象本身的代码。

通过创建具体的装饰器并传入基础对象,可以动态地扩展对象的功能。

在这里插入图片描述


三、装饰模式的应用场景

装饰模式在以下 4 4 4 种情况下使用,请同学们有个基本的了解。

  1. 动态地给一个对象添加额外的功能,而不影响其他对象。
  2. 需要在不改变原有代码的情况下,对现有对象进行扩展。
  3. 需要通过组合而非继承来实现功能的扩展。
  4. 需要对一个对象的功能进行多次扩展,而使用继承会导致类的爆炸性增长。

当然,装饰模式的应用场景有以下 4 4 4 类,请同学们认真学习。

  1. IO 流操作:Java 中的 InputStream、OutputStream 等类就是典型的装饰模式的应用。通过装饰器模式,我们可以在运行时动态地为输入输出流添加新的功能,如缓冲、压缩等,而不需要修改原有的 IO 类。
  2. GUI 组件:在 GUI 应用程序中,我们经常需要为组件添加额外的装饰,如边框、滚动条等。装饰模式可以让我们在不改变组件类的情况下,动态地添加这些装饰。
  3. 日志记录:通过装饰模式,我们可以为日志记录器对象动态地添加新的功能,如加密、压缩等,而不需要修改原有的日志记录器类。
  4. 数据库操作:在数据库操作中,我们可以通过装饰模式为数据库连接对象添加额外的功能,如连接池管理、事务管理等。

总之,装饰模式在需要动态地为对象添加功能、扩展对象的行为且不改变原有代码的情况下,提供了一种灵活且可复用的方案。

在这里插入图片描述


四、装饰模式面试题

  1. 请解释什么是装饰模式,并举一个具体的例子。
  2. 装饰模式和继承有什么区别?
  3. 装饰模式的优点和缺点是什么?
  4. 装饰模式与适配器模式有何异同?
  5. 在什么情况下应该使用装饰模式?
  6. 装饰模式如何实现动态地给对象添加新的功能?
  7. 装饰模式中的组件接口和装饰器接口有何作用?
  8. 在装饰模式中,装饰器可以有多个吗?如果可以,如何管理多个装饰器之间的顺序?
  9. 装饰模式与代理模式有何区别?
  10. 装饰模式是否违反开闭原则?为什么?

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/131879.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

春秋云镜 CVE-2015-1427

春秋云镜 CVE-2015-1427 ElasticSearch RCE 靶标介绍 ElasticSearch RCE 启动场景 漏洞利用 因查询时至少要求es中有一条数据,所以发送如下数据包,增加一个数据: POST /website/blog/ HTTP/1.1 Host: eci-2zedttamjkr80i9iubel.cloudeci…

VMware ubuntu空间越用越大

前言 用Ubuntu 1604编译了RK3399的SDK,之后删了一些多余的文件,df - h 已用21G,但window硬盘上还总用了185GB,采用了碎片整理,压缩无法解决 1 启动Ubuntu后, 安装 VMware Tools(T) 、 2 打开ubuntu终端,压…

Revit SDK 介绍:Ribbon 界面

前言 Revit 通过 API 将完整的 Ribbon 做了保留,同时这些菜单按钮也可以和相应的命令绑定。 内容 运行效果如下所示: 菜单特写: Ribbon Sample 整体是 API 暴露出来的一个 RibbonPanel,对应的接口: namespace Au…

FPGA GTH aurora 8b/10b编解码 PCIE 视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTH 全网最细解读GTH 基本结构GTH 发送和接收处理流程GTH 的参考时钟GTH 发送接口GTH 接收接口GTH IP核调用和使用 4、设计思路框架视频源选择silicon9011解码芯片配置及采集动态彩条视频数据组包GTH aurora 8b/10…

Java native 关键字

如你在看 JDK 的源代码的时候,大概率会看到很多方法使用了 native 关键字。 下面是 String 对象 JDK 中的源代码,就带有了一个 native 关键字。 native 是干什么用的 简单来说就是 Java 的 native 方法的实现不是用 Java 实现的,可能在其他…

Flutter 中的单元测试:从工作流基础到复杂场景

对 Flutter 的兴趣空前高涨——而且早就应该出现了。 Google 的开源 SDK 与 Android、iOS、macOS、Web、Windows 和 Linux 兼容。单个 Flutter 代码库支持所有这些。单元测试有助于交付一致且可靠的 Flutter 应用程序,通过在组装之前先发制人地提高代码质量来确保不…

数据结构与算法(二)——前缀、中缀、后缀表达式

一、前缀表达式(波兰表达式) 1.1、计算机求值 从右至左扫描表达式,遇到数字时,将数字压入堆栈。遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素&#xff09…

Navicat导入Excel数据顺序变了

项目场景: Navicat导入Excel数据 问题描述 从Excel表格中导入数据到数据库中。但是,在导入的过程中,我们常会发现数据顺序出现了问题,导致数据错位,给数据的处理带来了极大的麻烦。 原因分析: 这个问题的…

mybatisplus配置拦截器实现保存加密,输出解密,模糊查询

前言:因公司需求需要把某些实体类的某些字段值进行加密保存,在查询时解密明文输出。现记录两种方式。 一、第一种方式: (1)使用TableField(typeHandler TypeHandler.class)注解自带的字段类型处理器,写一…

电脑死机的时候,CPU到底在做什么?

电脑死机,应该每个接触计算机的小伙伴都经历过吧。 尤其是早些年,电脑配置还没现在这么高的时候,多开几个重量级应用程序,死机就能如约而至,就算你把键盘上的CTRLALTDELETE按烂了,任务管理器也出不来&…

Mybatis-Genertor逆向工程

1、导入mybaties插件 <build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.2</version><dependencies><dependency>…

Error: svn: E155004: Run ‘svn cleanup‘ to remove locks

解决办法如下&#xff1a;点击settings 点击清除缓存按钮&#xff0c;然后再使用svn进行提交更新操作&#xff0c;但是可能还会有其它的错误&#xff0c;比如svn: E230001: Server SSL certificate verification failed&#xff0c;解决这个错误请参考我另一篇文章&#xff1a;…

博客系统(升级(Spring))(一)创建数据库,创建实例化对象,统一数据格式,统一报错信息

博客系统&#xff08;一&#xff09; 博客系统一、创建项目二、建立数据库结构链接服务器和数据库和Redis 三、创建实例化对象四、统一数据结构结构 五、统一报错信息 博客系统 博客系统是干什么的&#xff1f; CSDN就是一个典型的博客系统。而我在这里就是通过模拟实现一个博…

Python+Requests+Excel接口测试实战

1、EXCEL文件接口保存方式&#xff0c;如图。 2、然后就是读取EXCEL文件中的数据方法&#xff0c;如下&#xff1a; 1 import xlrd2 3 4 class readExcel(object):5 def __init__(self, path):6 self.path path7 8 property9 def getSheet(self): 10 …

莫比乌斯召回系统介绍

当前召回系统只能召回相关性高的广告&#xff0c;但不能保证该广告变现能力强。莫比乌斯做了如下两点创新&#xff1a; 在召回阶段&#xff0c;引入CPM等业务指标作为召回依据在召回阶段&#xff0c;引入CTR模型&#xff0c;从而召回更多相关性高且变现能力强的广告 参考 百度…

基于Protege的知识建模实战

一.Protege简介、用途和特点 1.Protege简介 Protege是斯坦福大学医学院生物信息研究中心基于Java开发的本体编辑和本体开发工具&#xff0c;也是基于知识的编辑器&#xff0c;属于开放源代码软件。这个软件主要用于语义网中本体的构建&#xff0c;是语义网中本体构建的核心开发…

Elasticsearch:什么是生成式人工智能?

生成式人工智能定义 给学生的解释&#xff08;基本&#xff09;&#xff1a; 生成式人工智能是一种可以创造新的原创内容的技术&#xff0c;例如艺术、音乐、软件代码和写作。 当用户输入提示时&#xff0c;人工智能会根据从互联网上现有示例中学到的知识生成响应&#xff0c;…

linux安装Sentinal1.8.6

前言&#xff1a; 使用docker search sentinel-dashboard命令&#xff0c;发现docker中的镜像版本过低&#xff0c;由于要配合使用1.8.6&#xff0c;所以这里采用java后台运行sentinel1.8.6-jar的方式。 1、官网下载对应版本jar&#xff08;https://github.com/alibaba/Sentin…

MySQL间隙锁深入分析

概念 什么是间隙锁&#xff1f; MySQL的间隙锁&#xff08;gap lock&#xff09;是一种锁定相邻数据间隔的机制。 触发时机&#xff1f; 当使用SELECT…FOR UPDATE或UPDATE语句时&#xff0c;MySQL会获取一个范围锁&#xff0c;包括指定条件内的所有数据行&#xff0c;并且还…

rhcsa4 进程和SSH

tree命令。用于以树状结构显示目录和文件。通过运行 “tree” 命令可视化地查看文件系统中的目录结构。 tree / systemd是第一个系统进程&#xff08;pid1&#xff09;不启动&#xff0c;其他进程也没法启动&#xff0c; 用pstree查看进程树 我们可以看到所有进程都是syste…