结构设计模式 -装饰器设计模式 - JAVA

装饰器设计模式

    • 一. 介绍
    • 二. 代码示例
      • 2.1 抽象构件(Component)角色
      • 2.2 具体构件(Concrete Component)角色
      • 2.3 装饰(Decorator)角色
      • 2.4 具体装饰(Concrete Decorator)角色
      • 2.5 测试 结果
    • 三. 结论
      • 3.1 优缺点
      • 3.2 使用场景

前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

一. 介绍

百度百科装饰模式指的是在不必改变原类文件使用继承的情况下,动态扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象

个人理解: java在编译完成后,我们无法动态的去为一个编译好的对象新增或者修改某个功能,这时候就可以通过装饰模式去设计

举例理解: 通常我们使用继承或者组合去扩展对象的行为,假如我们想要实现不同种类的手链,我们创建一个手链(Bracelet)接口,然后我们通过实现这个接口获取一个基本的手链(basic bracelet),我们可以在基本的手链的基础上进行扩展获得**金手链(Gold)和银手链(Silver)**结构图如下所示。

请添加图片描述

通过以上案例我们可以了解到,一些简单的扩展通过继承的方式就可以解决了,但如果我们还想在扩展,想要获取一个同时具备金色和银色的手链,并且还要添加某些功能,那么就会变得很复杂。如果手链类型增加,使用继承的实现逻辑就很难管理。这时候就可以通过装饰模式去设计

好了,上面的介绍都是再讲为什么要使用装饰模式,接下来就通过代码案例讲解装饰模式是怎么样子实现的,如何解决上面所说的问题

装饰模式有以下角色:

(1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。

(2)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。

(3)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。

(4)具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。

二. 代码示例

装饰模式代码具体流程如下

请添加图片描述

2.1 抽象构件(Component)角色

定义要实现的方法的接口或抽象类

/*** @author chenyunzhi* @date 2024/6/3 16:06* @Description 手链*/
public interface Bracelet {void color();}

2.2 具体构件(Concrete Component)角色

/*** @author chenyunzhi* @date 2024/6/3 16:08* @Description 基本的手链,也就是白色*/
public class BasicBracelet implements Bracelet{@Overridepublic void color() {System.out.print("基本的白色手链");}
}

2.3 装饰(Decorator)角色

/*** @author chenyunzhi* @date 2024/6/3 16:23* @Description 手链装饰器*/
public class BraceletDecorator implements Bracelet {/*** 装饰器类应该可以访问组件变量,因此我们将保护该变量*/protected Bracelet bracelet;public BraceletDecorator(Bracelet bracelet) {this.bracelet = bracelet;}@Overridepublic void color() {this.bracelet.color();}
}

2.4 具体装饰(Concrete Decorator)角色

金手链

/*** @author chenyunzhi* @date 2024/6/3 16:32* @Description 金手链*/
public class GoldBracelet extends BraceletDecorator{public GoldBracelet(Bracelet bracelet) {super(bracelet);}@Overridepublic void color() {super.color();System.out.print(",增加金色");}
}

银手链

/*** @author chenyunzhi* @date 2024/6/3 16:37* @Description 银手链*/
public class SilverBracelet extends BraceletDecorator{public SilverBracelet(Bracelet bracelet) {super(bracelet);}@Overridepublic void color() {super.color();System.out.print(",增加银色");}
}

2.5 测试 结果

/*** @author chenyunzhi* @date 2024/6/3 14:39* @Description*/
public class DecoratorPatternTest {public static void main(String[] args) throws Exception{// 获取金手链对象Bracelet goldBracelet = new GoldBracelet(new BasicBracelet());goldBracelet.color();System.out.println("\n-----------------------");// 获取银手链对象Bracelet silverBracelet = new SilverBracelet(new BasicBracelet());silverBracelet.color();System.out.println("\n-----------------------");// 获取包含金色和银色的手链Bracelet goldSilverBracelet = new GoldBracelet(new SilverBracelet(new BasicBracelet()));goldSilverBracelet.color();}
}

请添加图片描述

通过以上结果我们可以看到,如果我们想要获取包含 金色和银色的手链,可以通过组合金色和银色的装饰者对象来获取具有金色和银色手链。

三. 结论

3.1 优缺点

优点:

  • 装饰器设计模式有助于提供运行时修改能力,因此更加灵活。当选择数量较多时,易于维护和扩展。
  • 装饰器设计模式的缺点是它使用了很多相似类型的对象(装饰器)。
  • Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点

  • 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
  • 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
  • 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

3.2 使用场景

  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

    不能采用继承的情况主要有两类:

    • 第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;
    • 第二类是因为类定义不能继承(如final类)
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  • 当对象的功能要求可以动态地添加,也可以再动态地撤销时。

  • 装饰器模式在Java IO类中被大量使用,例如FileReader、BufferedReader等。

作者:神的孩子都在歌唱

本人博客:https://blog.csdn.net/weixin_46654114

转载说明:务必注明来源,附带本人博客连接。

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

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

相关文章

【鸿蒙HarmonyOS NEXT】用户首选项Preference存储数据

【鸿蒙HarmonyOS NEXT】数据存储之用户首选项Preference 一、环境说明二、Preference运作机制三、示例代码加以说明四、小结 一、环境说明 DevEco Studio 版本: API版本:以12为主 二、Preference运作机制 应用场景: 用户首选项为应用提…

在mac中如何使python3作为默认版本

在系统中同时安装了Python 2和Python 3,且二者的执行文件分别是python和python3。如果你执行python --version看到的是Python 2的版本,而执行python3 --version看到的是Python 3的版本,这表明系统能够正确区分两个版本。 如果你希望使用Pyth…

模型Alignment之RLHF与DPO

1. RLHF (Reinforcement Learning from Human Feedback) RLHF 是一种通过人类反馈来强化学习的训练方法,它能够让语言模型更好地理解和执行人类指令。 RLHF 的三个阶段 RLHF 的训练过程一般分为三个阶段: 监督微调(Supervised Fine-Tuning,…

TensorRT-LLM——优化大型语言模型推理以实现最大性能的综合指南

引言 随着对大型语言模型 (LLM) 的需求不断增长,确保快速、高效和可扩展的推理变得比以往任何时候都更加重要。NVIDIA 的 TensorRT-LLM 通过提供一套专为 LLM 推理设计的强大工具和优化,TensorRT-LLM 可以应对这一挑战。TensorRT-LLM 提供了一系列令人印…

.net core8 使用JWT鉴权(附当前源码)

说明 该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。 该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。 说明:OverallAuth2.0 是一个简单、易懂、功能强…

基于物联网技术的智能运动检测仪设计(微信小程序)(230)

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】整体构架1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要【5】项目背景1.4 开发工具的选择【1】设备端开发【2】微信小程序开发…

9.22学习记录

进程间通信方式 管道、有名管道、共享内存、消息队列、信号、信号量、套接字 JVM内存模型 私有:程序计数器、本地方法栈、虚拟机栈 公有部分:堆、方法区 equals和hashcode有什么区别和联系? equals默认比较两个对象的引用,但…

YOLOv8——测量高速公路上汽车的速度

引言 在人工神经网络和计算机视觉领域,目标识别和跟踪是非常重要的技术,它们可以应用于无数的项目中,其中许多可能不是很明显,比如使用这些算法来测量距离或对象的速度。 测量汽车速度基本步骤如下: 视频采集&#x…

记录一次ubuntu /mysql/redis/nginx等 系统安装

没想到还会做一次系统安装配置类的工作,没办法,碰到问题了,总得解决。 安装 &网络配置 从网上下载了ubuntu 18.04.6的安装包,用UltraISO做安装盘,到服务器上修改了下启动顺序,ubuntu的安装非常简单&a…

算法打卡:第十一章 图论part05

今日收获:并查集理论基础,寻找存在的路径 1. 并查集理论基础(from代码随想录) (1)应用场景:判断两个元素是否在同一个集合中 (2)原理讲解:通过一个一维数组…

游戏如何应对云手机刷量问题

云手机的实现原理是依托公有云和 ARM 虚拟化技术,为用户在云端提供一个安卓实例,用户可以将手机上的应用上传至云端,再通过视频流的方式,远程实时控制云手机。 市面上常见的几款云手机 原本需要手机提供的计算、存储等能力都改由…

python文件读写知识简记

简单记录一下python文件读写相关知识 一、打开文件 python使用open函数打开文件,函数原型如下 open(file, moder, buffering-1, encodingNone, errorsNone, newline None, closefdTrue, openerNone) file 文件地址 mode 文件打开模式,可设定为如下的…

深度学习实战:UNet模型的训练与测试详解

🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊 目录 1、云实例:配置选型与启动1.1 登录注册1.2 配置 SSH 密钥对1.3 创建实例1.4 登录云实例 2、云存储:数据集上传…

优选算法之 分治-快排

目录 一、颜色分类 1. 题目链接:75. 颜色分类 2. 题目描述: 3. 解法(快排思想 - 三指针法使数组分三块) 🌴算法思路: 🌴算法流程: 🌴算法代码: 二、快…

python写windows抓包工具, 直接使用windows api

主要使用python自带的ctypes和wintypes进行类型转换和交互 # python 3.11.7 import ctypes from ctypes import wintypes import inspect import socketdef log(data):print("----------------log start---------------")try:for attr, value in inspect.getmembers…

【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(上)

系列文章目录 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(上) 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(下) 文章目录 系列文章目录前言一、ArkTS基本介绍1、 ArkTS组成2、组件参数和属性2.1、区…

YOLOV8 OpenCV + usb 相机 实时识别

1 OpenCV 读相机 import cv2cap cv2.VideoCapture(0) while (1):# get a frameret, frame cap.read()# show a framecv2.imshow("capture", frame)if cv2.waitKey(1) & 0xFF ord(q):# cv2.imwrite("/opt/code/image/fangjian2.jpeg", frame)#passb…

Linux基础知识-1

Linux和Windows最大差异:目录。在Windows中,磁盘是被分成了很多区的,比如C盘,D盘,不同的文件放在不同的盘下面。下图为Windows的磁盘管理,可以看到磁盘0被划分为了不同的区域,C盘,D盘等&#xf…

[深度学习]Pytorch框架

1 深度学习简介 应用领域:语音交互、文本处理、计算机视觉、深度学习、人机交互、知识图谱、分析处理、问题求解2 发展历史 1956年人工智能元年2016年国内开始关注深度学习2017年出现Transformer框架2018年Bert和GPT出现2022年,chatGPT出现,进入AIGC发展阶段3 PyTorch框架简…

Leetcode 第 139 场双周赛题解

Leetcode 第 139 场双周赛题解 Leetcode 第 139 场双周赛题解题目1:3285. 找到稳定山的下标思路代码复杂度分析 题目2:3286. 穿越网格图的安全路径思路代码复杂度分析 题目3:3287. 求出数组中最大序列值思路代码复杂度分析 题目4:…