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

【设计模式】之装饰器模式

系列文章目录

  • 【设计模式】之模板方法模式

  • 【设计模式】之责任链模式

  • 【设计模式】之策略模式

  • 【设计模式】之工厂模式(三种)


前言

今天给大家介绍23种设计模式中的装饰器模式。🌈

一、什么是装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

在装饰器模式中,有一个抽象组件接口,所有具体组件和装饰器都实现了这个接口。装饰器持有一个指向抽象组件的引用,并通过递归的方式调用接口中的操作。每个装饰器都可以添加自己的功能,同时调用所装饰的对象的操作。

二、装饰器模式的角色

Component(抽象组件)定义了一个对象的接口,可以给这些对象动态地添加职责(即方法)
ConcreteComponent(具体组件)实现了Component接口,是装饰器要装饰的真实对象
Decorator(装饰器)
  • 持有一个指向Component对象的引用,并有一个和Component接口一致的接口。
  • 它可以给组件添加额外的职责(方法)。
  • 通常包含对Component对象的引用以及实现Component接口的方法,这些方法会调用Component接口中定义的操作,并可能在其前后添加新的行为
ConcreteDecorator(具体装饰器)实现了Decorator接口,是装饰器接口的具体实现类

三、示例

定义一个抽象组件:

public interface Person {Double cost();void show();
}

具体组件:

public class XiaoJie implements Person{@Overridepublic Double cost() {return 0.0;}@Overridepublic void show() {System.out.println("没穿衣服的小杰。");}
}

 定义装饰器

public abstract class ClothesDecorator implements Person{protected Person person;public ClothesDecorator(Person person) {this.person = person;}
}

 具体装饰器:

public class Shirt extends ClothesDecorator{public Shirt(Person person) {super(person);}@Overridepublic Double cost() {return this.person.cost()+500;}@Overridepublic void show() {this.person.show();System.out.println("买了一个体恤,累计消费:" + this.cost() + "元");}
}public class Jeans extends ClothesDecorator{public Jeans(Person person) {super(person);}@Overridepublic Double cost() {return this.person.cost()+200.0;}@Overridepublic void show() {this.person.show();System.out.println("买了一条牛仔裤,累计消费:"+this.cost()+"元");}
}public class Shoes extends ClothesDecorator{public Shoes(Person person) {super(person);}@Overridepublic Double cost() {return this.person.cost()+1000.0;}@Overridepublic void show() {this.person.show();System.out.println("买了一双鞋,一共消费:"+this.cost()+"元");}
}

测试:

public class test {public static void main(String[] args) {Person xiaoJie = new XiaoJie();xiaoJie = new Shirt(xiaoJie);xiaoJie = new Jeans(xiaoJie);xiaoJie = new Shoes(xiaoJie);xiaoJie.show();System.out.println("本次一共消费:"+xiaoJie.cost()+"元");}
}
/*
测试结果:没穿衣服的小杰。
买了一个体恤,累计消费:500.0元
买了一条牛仔裤,累计消费:700.0元
买了一双鞋,一共消费:1700.0元
本次一共消费:1700.0元*/

 四、应用场景

  1. 扩展类的功能:当需要给一个已经存在的类添加新的功能,但又不想通过继承来生成子类时,可以使用装饰器模式。这是因为继承会增加类的层次结构,可能导致类的数量爆炸式增长,而装饰器模式可以在不改变原有类结构的情况下,动态地给对象添加新的功能。
  2. 动态添加和撤销功能:装饰器模式允许在运行时动态地给对象添加新的功能,并且这些功能也可以动态地被撤销。这对于那些需要经常变化或需要灵活配置的功能来说非常有用。
  3. 为一组相似的类添加功能:如果有一组相似的类,它们都需要添加相同的功能,但是又不希望修改这些类的源代码,那么可以使用装饰器模式。通过为这些类创建一个统一的接口或抽象类,并创建一个装饰器类来包装这些类的对象,就可以在保持原有类结构不变的情况下,为这些类添加新的功能。
  4. 处理透明性和递归组合:装饰器模式可以透明地添加或撤销功能,这意味着用户在使用被装饰的对象时,不需要知道对象是否被装饰过。此外,装饰器模式还可以实现递归组合,即一个装饰器可以包含另一个装饰器,从而创建出更复杂的功能组合。

在实际应用中,装饰器模式可以用于许多场景,例如:

  • 在图形界面库中,可以使用装饰器模式来动态地改变控件的外观或行为。
  • 在网络编程中,可以使用装饰器模式来添加日志记录、性能监控等功能到现有的网络请求或响应对象中。
  • 在游戏开发中,可以使用装饰器模式来扩展游戏角色的能力或属性。
  • 在Web应用中,可以使用装饰器模式来动态地添加或撤销用户的权限或角色。

总之,装饰器模式是一种非常灵活和强大的设计模式,它可以在不改变现有类结构的情况下,动态地给对象添加新的功能或职责。

五、总结

优点

  • 动态扩展:装饰器模式允许在运行时动态地给一个对象添加新的功能或职责,而无需修改其原有结构。这使得代码更加灵活和可扩展。

  • 高内聚低耦合:通过组合而非继承来扩展对象的功能,有助于保持类的职责单一,实现高内聚。同时,由于装饰器与被装饰对象之间通过接口或抽象类进行交互,降低了它们之间的耦合度。

  • 透明性:对于使用装饰器模式的客户端代码来说,装饰过的对象与未装饰的对象在接口上是一致的,因此可以透明地使用装饰过的对象。客户端无需知道对象是否被装饰过,也无需关心装饰的具体细节。

  • 灵活性:装饰器模式允许在运行时通过组合不同的装饰器来创建具有不同功能组合的对象。这使得可以根据需要灵活地定制对象的行为。

缺点

  • 可能产生较多的对象:由于装饰器模式是通过组合多个装饰器来扩展对象的功能的,因此在使用时可能会产生较多的对象。这可能会导致内存占用增加和性能下降的问题。

  • 对装饰器的要求:装饰器需要与被装饰对象具有相同的接口或抽象类。如果接口或抽象类发生变化,可能需要修改所有的装饰器。这可能会增加维护成本。

  • 可能导致设计过度复杂化:如果过度使用装饰器模式,可能会导致设计过度复杂化。过多的装饰器类和接口可能会使代码难以理解和维护。

  • 递归调用:在某些情况下,装饰器可能会递归地调用自身或其他装饰器。这可能会导致无限递归或栈溢出的问题,需要特别注意。


总结

今天的分享就到这里,我们下期再见✋

相关文章:

【设计模式】之装饰器模式

系列文章目录 【设计模式】之模板方法模式 【设计模式】之责任链模式 【设计模式】之策略模式 【设计模式】之工厂模式(三种) 前言 今天给大家介绍23种设计模式中的装饰器模式。🌈 一、什么是装饰器模式 装饰器模式(Decora…...

leetcode_46.全排列

46. 全排列 题目描述:给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#…...

【牛客】[HNOI2003]激光炸弹

原题链接:登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 二维前缀和板题。 注意从(1,1)开始存即可,所以每次输入x,y之后,要x,y。 因为m的范围最大为…...

Docker与Harbor:构建企业级私有Docker镜像仓库

目录 引言 一、本地私有仓库 (一)基本概述 (二)搭建本地私有仓库 1.下载registry镜像 2.启动容器 3.上传本地镜像 4.客户端下载镜像 二、Harbor简介 (一)什么是 Harbor (二&#xff…...

推荐几个傻瓜式短视频去水印在线网站

在数字化时代,短视频已成为信息传播的重要方式之一。随着TikTok、Instagram Reels、抖音等平台的流行,短视频的制作和分享成为了日常生活的一部分。然而,在分享或编辑这些短视频时,去除水印成为了一项不可或缺的需求。水印是视频原…...

大模型LLM之SFT微调总结

一. SFT微调是什么 在大模型的加持下现有的语义理解系统的效果有一个质的飞跃;相对于之前的有监督的Pre-Train模型;大模型在某些特定的任务中碾压式的超过传统nlp效果;由于常见的大模型参数量巨大;在实际工作中很难直接对大模型训…...

【RocketMQ问题总结-2】

RocketMQ 消息持久化 Broker通过底层的Netty服务器获取到一条消息后,会把这条消息的内容写入到一个CommitLog文件里去(一个Broker进程就只有一个CommitLog文件,也就是说这个Broker上所有Topic的消息都会写入这个文件)。 同时&…...

掌握Android Fragment开发之魂:Fragment的深度解析(上)

Fragment是Android开发中用于构建动态和灵活界面的基石。它不仅提升了应用的模块化程度,还增强了用户界面的动态性和交互性,允许开发者将应用界面划分为多个独立、可重用的部分,每个部分都可以独立于其他部分进行操作。本文将从以下几个方面深…...

深度解读DreamFusion:一站式AI解决方案

DreamFusion是一款备受瞩目的人工智能解决方案,它整合了多种AI技术,为用户提供了一站式的解决方案。本文将全面解读DreamFusion,探讨其特点、功能和应用场景,助您深入了解这一创新工具。 1. 特点概述 DreamFusion具备以下显著特…...

JVM-02

字节码文件是一种特殊的文件格式,它包含了将源代码转换为机器可执行代码所需的指令集。字节码文件通常是由编译器将源代码编译为字节码的中间表示形式。 在Java中,字节码文件的扩展名为.class,它存储了编译后的Java代码。这些字节码文件可以在…...

【一起深度学习——NIN】

NIN神经网络 原理图:代码实现:输出结果: 原理图: 代码实现: import torch from torch import nn from d2l import torch as d2ldef nin_block(in_channels, out_channels, kernel_size, strides, padding):return nn.…...

数字工厂管理系统如何助力企业数据采集与分析

随着科技的不断进步,数字化已成为企业发展的重要趋势。在制造业领域,数字工厂管理系统的应用日益广泛,它不仅提升了生产效率,更在数据采集与分析方面发挥着举足轻重的作用。本文旨在探讨数字工厂管理系统如何助力企业数据采集与分…...

uniap之微信公众号支付

近来用uniapp开发H5的时候,需要接入支付,原来都是基于后端框架来做的,所以可谓是一路坑中过,今天整理下大致流程分享给大家。 先封装util.js,便于后面调用 const isWechat function(){return String(navigator.userA…...

Django知识点总结

因为最近在搞一个Python项目,使用的Django框架。所以快速学习了一下这个web框架。并做一些总结。 Django官网的介绍:Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Built by experience…...

算法(C++

题目:螺旋矩阵(59. 螺旋矩阵 II - 力扣(LeetCode)) 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入&am…...

Python专题:六、循环语句(1)

补充知识 代码的注释 #描述性文字 阅读代码的人更好的理解代码 while循环语句 x<100条件控制语句&#xff0c;Totalx,Total自增加x&#xff0c;x1&#xff0c;x自增加1&#xff0c;x<100此条件满足时&#xff0c;执行while循环&#xff0c;当x101时&#xff0c;x101条…...

力扣2105---给植物浇水II(Java、模拟、双指针)

题目描述&#xff1a; Alice 和 Bob 打算给花园里的 n 株植物浇水。植物排成一行&#xff0c;从左到右进行标记&#xff0c;编号从 0 到 n - 1 。其中&#xff0c;第 i 株植物的位置是 x i 。 每一株植物都需要浇特定量的水。Alice 和 Bob 每人有一个水罐&#xff0c;最初是…...

Windows设置Redis为开机自启动

前言 Redis作为当前最常用的当前缓存技术&#xff0c;基本上Web应用中都有使用。所以&#xff0c;每次我们在本地启动项目前&#xff0c;都必须将Redis服务端启动。但是&#xff0c;每次都要去启动Redis就很麻烦&#xff0c;有没有办法做到开机自动启动Redis呢&#xff1f;这当…...

行业早报5.10

1.鸿蒙智行 4 月交付 29632 辆蝉联中国新势力月销冠&#xff0c;问界 M9 超 13000 辆&#xff1b; 2.三星收购胎儿超声 AI 软件公司 Sonio&#xff0c;巩固尖端医疗设备领域的领先地位&#xff1b; 3.蔚来汽车 4 月交付 15620 辆新车&#xff0c;同比增长 134.6%&#xff1b; 4…...

Java+SpringBoot+JSP实现在线心理评测与咨询系统

前言介绍 随着互联网技术的高速发展&#xff0c;人们生活的各方面都受到互联网技术的影响。现在人们可以通过互联网技术就能实现不出家门就可以通过网络进行系统管理&#xff0c;交易等&#xff0c;而且过程简单、快捷。同样的&#xff0c;在人们的工作生活中&#xff0c;也就…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里

写一个shell脚本&#xff0c;把局域网内&#xff0c;把能ping通的IP和不能ping通的IP分类&#xff0c;并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...