当前位置: 首页 > news >正文

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. 装饰模式是否违反开闭原则?为什么?

在这里插入图片描述

相关文章:

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

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

Linux学习之MySQL备份

xtrabackup资源下载 完全备份与恢复 # 1.物理备份与恢复 # 冷备份,需停止数据库服务 适合线下服务器。 [rootmysql50 ~]# systemctl stop mysqld [rootmysql50 ~]# mkdir /bakdir [rootmysql50 ~]# cp -r /var/lib/mysql /bakdir/mysql.bak [rootmysql50 ~]# cd /…...

时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化

时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化 目录 时序分解 | MATLAB实现北方苍鹰优化算法NGO优化VMD信号分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 北方苍鹰优化算法NGO优化VMD,对其分解层数,惩罚因子数做优化…...

分类预测 | Matlab实现RBF-Adaboost多特征分类预测

分类预测 | Matlab实现RBF-Adaboost多特征分类预测 目录 分类预测 | Matlab实现RBF-Adaboost多特征分类预测效果一览基本介绍研究内容程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于RBF-Adaboost数据分类预测(Matlab完整程序和数据) 2.多特征输入…...

【Java代码规范】阿里编码规约 VS CheckStyle

全文速览: 1、关于代码编码质量2、如何小成本有效管理企业内的编码规范 2.1 阿里编码规约IDE插件2.2 CheckStyle IDE插件 3、如何在代码提交中检验规范 3.1 阿里编码规约配置git precommit check3.2 CheckStyle配置git precommit check3.3 实践 1、关于代码编码质…...

iPhone苹果15手机圆点怎么设置让屏幕上显示出来圆形图标?

iPhone苹果15手机圆点怎么设置让屏幕上显示出来圆形图标? 1、在iPhone苹果手机上找到「设置」并点击打开; 2、在苹果iPhone设置内找到「辅助功能」并点击打开; 3、在苹果iPhone手机辅助功能内的动作交互内找到「触控」并点击打开&#xff1b…...

kibana报错内存溢出问题解决

一、背景: kibana内存溢出,进程被kill掉,导致前端页面访问不到。 报错内容 二、报错原因: 发现是前端 js 报的内存 oom 异常,通过网上资料发现node.js 的默认内存大小为1.4G Node 中通过 JavaScript 使用内存时只能…...

【C语法】1124循环结构

#include <stdio.h> int main(){ //输入一个数。倒叙输出各个位上的数。 //123456 6 5 4 3 2 1 // 1输出个位上的数 %10 // 2将这个数去掉个位上的数。 / 10 // 3当这个数最后变成0时结束 int a 0; printf("请输入一个正整数&#xff1a;"); scanf…...

在PHP8中向数组添加元素-PHP8知识详解

在php8中向数组添加元素有多种方法&#xff0c;在这里主要讲解几个常用的方法&#xff1a;使用方括号[]添加元素、使用array_unshift()函数&#xff0c;向数组的头部添加元素、使用array_push()函数&#xff0c;向数组的尾部添加元素、使用array_splice()函数添加元素。 1、使用…...

Drupal __ 8.5.0 __ XSS文件上传 __CVE-2019-6341

Drupal __ 8.5.0 __ XSS文件上传 __CVE-2019-6341 说明内容漏洞编号CVE-2019-6341漏洞名称Drupal XSS漏洞漏洞评级中危影响范围在7.65之前的Drupal 7版本中&#xff1b; 8.6.13之前的Drupal 8.6版本; 8.5.14之前的Drupal 8.5版本。漏洞描述Drupal诞生于2000年&#xff0c;是一…...

Pycharm中配置Celery启动

Pycharm中配置Celery启动 前置条件 目录结构 ----FerDemo --------celery_demo ------------tasks.py tasks.py文件代码 import sys import time from celery import Celeryapp Celery(demo,backendredis://:password127.0.0.1/0,brokerredis://:password127.0.0.1/1,broker…...

Jmeter —— 常用的几种断言方法(基本用法)

在使用JMeter进行性能测试或者接口自动化测试工作中&#xff0c;经常会用到的一个功能&#xff0c;就是断言&#xff0c;断言相当于检查点&#xff0c;它是用来判断系统返回的响应结果是否正确&#xff0c;以此帮我们判断测试是否通过&#xff0c;本文 主要介绍几种常用的断言&…...

mybatis bean属性识别丢失【NoSuchPropertyException】

背景 发现线上报错日志 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression Cause: org.apache.ibatis.ognl.NoSuchPropertyException: 参考 https://github.com/mybatis/mybatis-…...

点云从入门到精通技术详解100篇-基于补全点云与图像像素级融合的障碍物识别

目录 前言 感知融合技术研究现状及问题 感知融合技术概述 特征级融合研究现状...

商品分类显示scroll-view布局实现

快捷键 view{菜单数据$}*40 回车后即可快速生成 <view class="cates"> <!-- 搜索开始 --><SearchBar></SearchBar> <!-- 搜索结束 --> <view class="cates_container"> <!-- 左侧菜单 开始 --> <scroll-vie…...

基本的SELECT语句——“MySQL数据库”

各位CSDN的uu们好呀&#xff0c;好久没有更新小雅兰的MySQL数据库专栏啦&#xff0c;接下来一段时间&#xff0c;小雅兰都会更新MySQL数据库的知识&#xff0c;下面&#xff0c;让我们进入今天的主题吧——基本的SELECT语句&#xff01;&#xff01;&#xff01; SQL概述 SQL语…...

DedeCMS5.7远程文件包含漏洞分析

看一段php代码 <?php foreach(Array(_GET,_POST,_COOKIE) as $_request){foreach($$_request as $_k > $_v) ${$_k} $_v; }echo a:.$a;echo b:.$b;这段代码可以实现创建变量并赋值的操作&#xff0c;而且参数都是可控的。 如果之前已经有了相应参数&#xff0c;那就会…...

GpsAndMap模块开源,欢迎测评

背景 之前的文章有提到&#xff0c;最近在使用folium的过程中&#xff0c;深感对于一个非专业人员来说&#xff0c;GPS坐标以及其所隐含的GPS坐标系&#xff0c;以及不同GPS坐标系之间的相互转换关系&#xff0c;不是一个十分清晰的概念&#xff0c;往往造成在使用GPS坐标在fo…...

DHT11 温湿度传感器

目录 1.DHT11 温湿度传感器概述 2.检测DHT11温湿度传感器模块是否存在 3.通过编写代码读取温湿度数据​编辑 4.将读取到的温湿度数据通过串口上传 1.DHT11 温湿度传感器概述 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器&#xff0c;应用领域&am…...

vue3 自定义Hooks

文章目录 前言一、Hooks是什么&#xff1f;二、图片转换Base641.Hooks2.使用 三、监听元素宽高&#xff08;自定义指令Hooks&#xff09;1.Hooks2.使用 总结 前言 本文主要记录了vue3学习中自定义Hooks和vue2中Mixins的使用与案例。 一、Hooks是什么&#xff1f; Hooks用来处…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...