二十三种设计模式全面解析-装饰器模式的高级应用:打造灵活可扩展的通知系统
在现代软件开发中,通知系统是一个广泛应用的功能,用于实时向用户发送各种类型的通知,如短信、微信、邮件以及系统通知。然而,通知系统的需求通常是多变且动态的,因此需要一种灵活可扩展的设计模式来满足不同类型的通知需求。
在前面一篇文章中,我们介绍了什么是装饰器模式?以及装饰器模式的适用场景和技术点,并以简单的案例进行了说明,感兴趣的朋友请前往查看。
相信阅读了上一篇文章的朋友,就知道,装饰器模式即可完全满足上述的通知需求。
那么今天我们就介绍如何利用装饰器模式来构建一个高度可定制的通知系统,实现通知的动态组合和扩展。
一、关键技术点回顾
装饰器模式是一种结构型设计模式,允许在不改变现有对象结构的情况下,动态地添加功能。
在通知系统中,我们可以将各种通知类型(短信、微信、邮件、系统通知)视为组件,而装饰器则用于为这些组件添加额外的通知功能。
二、实现案例代码
下面是一个简化的通知系统的装饰器模式实现的示例代码:
// 抽象构件 - 通知接口
interface Notification {void send(String message);
}// 具体构件 - 短信通知
class SMSNotification implements Notification {@Overridepublic void send(String message) {System.out.println("发送短信通知:" + message);}
}// 具体构件 - 微信通知
class WeChatNotification implements Notification {@Overridepublic void send(String message) {System.out.println("发送微信通知:" + message);}
}// 具体构件 - 邮件通知
class EmailNotification implements Notification {@Overridepublic void send(String message) {System.out.println("发送邮件通知:" + message);}
}// 具体构件 - 系统通知
class SystemNotification implements Notification {@Overridepublic void send(String message) {System.out.println("发送系统通知:" + message);}
}// 装饰器 - 抽象装饰器类
abstract class NotificationDecorator implements Notification {protected Notification notification;public NotificationDecorator(Notification notification) {this.notification = notification;}@Overridepublic void send(String message) {notification.send(message);}
}// 具体装饰器 - 短信通知装饰器
class SMSNotificationDecorator extends NotificationDecorator {public SMSNotificationDecorator(Notification notification) {super(notification);}@Overridepublic void send(String message) {super.send(message);sendSMS(message);}private void sendSMS(String message) {System.out.println("额外发送短信通知:" + message);}
}// 具体装饰器 - 微信通知装饰器
class WeChatNotificationDecorator extends NotificationDecorator {public WeChatNotificationDecorator(Notification notification) {super(notification);}@Overridepublic void send(String message) {super.send(message);sendWeChat(message);}private void sendWeChat(String message) {System.out.println("额外发送微信通知:" + message);}
}
以下是客户端代码:
public class Client {public static void main(String[] args) {// 创建基础通知对象Notification notification = new SystemNotification();// 使用装饰器动态添加短信通知和微信通知notification = new SMSNotificationDecorator(notification);notification = new WeChatNotificationDecorator(notification);// 发送通知notification.send("您有新的消息,请注意查收!");// 输出:// 发送系统通知:您有新的消息,请注意查收!// 额外发送短信通知:您有新的消息,请注意查收!// 额外发送微信通知:您有新的消息,请注意查收!}
}
在以上代码中,我们首先创建了一个基础的通知对象,即SystemNotification。
然后,通过装饰器模式,我们动态地为该通知对象添加了短信通知和微信通知功能,分别使用SMSNotificationDecorator和WeChatNotificationDecorator进行装饰。
最后,我们调用send方法发送通知,触发通知的发送。
三、总结
装饰器模式为通知系统提供了一种灵活可扩展的设计方案,使得我们能够动态地组合不同类型的通知并添加额外的功能,而无需修改现有代码。通过使用装饰器模式,我们可以轻松地扩展通知系统以满足不断变化的需求。
然而,装饰器模式并不仅限于通知系统。它在许多其他领域也有广泛的应用,如图形用户界面(GUI)的设计、输入输出流的处理等。通过理解装饰器模式的核心思想和实现方式,我们可以在实际的软件开发中更好地应用它,提高代码的灵活性和可维护性。
值得注意的是,装饰器模式还有许多其他的扩展和变体形式,例如使用透明装饰器、使用多个装饰器链等。这些扩展和变体可以根据具体需求进行选择和应用。
下一篇博文中,我们将继续研究更多设计模式,为您揭示更多的技巧和技术,敬请期待~
好了,今天的分享到此结束。如果觉得我的博文帮到了您,您的点赞和关注是对我最大的支持。如遇到什么问题,可评论区留言。
相关文章:
二十三种设计模式全面解析-装饰器模式的高级应用:打造灵活可扩展的通知系统
在现代软件开发中,通知系统是一个广泛应用的功能,用于实时向用户发送各种类型的通知,如短信、微信、邮件以及系统通知。然而,通知系统的需求通常是多变且动态的,因此需要一种灵活可扩展的设计模式来满足不同类型的通知…...
使用脚本整合指定文件/文件夹,执行定制化 ESLint 命令
背景 最近面对一个庞大的项目,但是只需要修改某个模块,每次都手搓命令太麻烦了,于是就想着能不能写个脚本来辅助处理这些事情。 解决方案 定制化一键 ESLint,执行文件下载地址: https://github.com/mazeyqian/go-g…...
C++ static与类
C static与类 1. 不和对象直接相关的数据,声明为static2. static成员函数没有this指针3.在类的外部定义static成员变量4.static与类的一些小应用 1. 不和对象直接相关的数据,声明为static 想象有一个银行账户的类,每个人都可以开银行账户。存…...
数据结构之堆的实现(图解➕源代码)
一、堆的定义 首先明确堆是一种特殊的完全二叉树,分为大根堆和小根堆,接下来我们就分别介绍一下这两种不同的堆。 1.1 大根堆(简称:大堆) 在大堆里面:父节点的值 ≥ 孩子节点的值 我们的兄弟节点没有限制&…...
持续集成部署-k8s-配置与存储-配置管理:ConfigMap
持续集成部署-k8s-配置与存储-配置管理:ConfigMap 1. ConfigMap 简介2. 创建 ConfigMap3. ConfigMap 环境变量与配置文件加载3.1 环境变量的使用3.2 配置文件加载1. ConfigMap 简介 在Kubernetes (K8s) 中,ConfigMap是一种用于存储配置数据的API对象。它用于将应用程序的配置…...
【漏洞复现】Apache_HTTP_2.4.50_路径穿越漏洞(CVE-2021-42013)
感谢互联网提供分享知识与智慧,在法治的社会里,请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证方式一 curl方式二 bp抓捕 1.5、修复建议 说明内容漏洞编号CVE-2021-42013漏洞名称…...
【KVM】软件虚拟化和硬件虚拟化类型
前言 大家好,我是秋意零。 今天介绍的内容是虚拟化技术以及软件虚拟化和硬件虚拟化。 👿 简介 🏠 个人主页: 秋意零🔥 账号:全平台同名, 秋意零 账号创作者、 云社区 创建者🧑 个…...
ES-初识ES
文章目录 介绍ElasticSearchElasticSearch的主要功能ElasticSearch的主要特性ElasticSearch的家族成员LogStashKibanaBeats ELK(ElasticSearch LogStash Kibana)的应用场景与数据库集成指标采集/日志分析 安装和配置ElasticSearch一、安装1、下载ES安装…...
foreach、for in和for of的区别?
foreach,for...in和for...of是三种不同的循环结构,它们在JavaScript中用来遍历数组或对象的属性。它们有一些重要的区别,以及各自的优点和适用情况。 1.foreach:这是最普通的循环结构,它遍历数组或对象的每一个元素或属…...
CVE-2023-21839 weblogic rce漏洞复现
文章目录 一、漏洞影响版本二、漏洞验证三、启动反弹shell监听切换路径到jdk1.8 四、启动ldap服务五、使用CVE-2023-21839工具来进行攻击测试六、反弹shell 一、漏洞影响版本 CVE-2023-21839是Weblogic产品中的远程代码执行漏洞,由于Weblogic IIOP/T3协议存在缺陷&…...
MQTT java代码演示
以下是使用Eclipse Paho客户端库的Java代码示例,用于连接到MQTT代理并发布和订阅消息。 首先,需要添加Maven依赖项到项目中: <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId>…...
Windows环境下使用VLC获取到大疆无人机的RTMP直播推流
1.环境准备 1.安装nginx 1.7.11.3 Gryphon 下载地址:http://nginx-win.ecsds.eu/download/ 下载nginx 1.7.11.3 Gryphon.zip,解压后修改文件夹名称为nginx-1.7.11.3-Gryphon; 2.安装nginx-rtmp-module 下载地址:GitHub - arut…...
【SpringBoot笔记42】SpringBoot集成knife4j生成接口文档
这篇文章,主要介绍SpringBoot如何集成knife4j及生成接口文档。 目录 一、knife4j接口文档生成器 1.1、接口文档工具介绍 1.2、引入依赖...
Go类型嵌入介绍和使用类型嵌入模拟实现“继承”
Go类型嵌入介绍和使用类型嵌入模拟实现“继承” 文章目录 Go类型嵌入介绍和使用类型嵌入模拟实现“继承”一、独立的自定义类型二、继承三、类型嵌入3.1 什么是类型嵌入 四、接口类型的类型嵌入4.1 接口类型的类型嵌入介绍4.2 一个小案例 五、结构体类型的类型嵌入5.1 结构体类…...
【深度学习】pytorch——实现CIFAR-10数据集的分类
笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 往期文章: 【深度学习】pytorch——快速入门 CIFAR-10分类 CIFAR-10简介CIFAR-10数据集分类实现步骤一、数据加载及预处理实现数据加载及预处理归一化的理解访问数据集Dataset对象Dataloader对象 二、…...
Datawhale-AIGC实践
Datawhale-AIGC实践 部署ChatGLM3-6B平台 clone 项目,配置环境 git clone https://github.com/THUDM/ChatGLM3.git cd ChatGLM3 pip install -r requirement.txt修改web_demo.py, web_demo2.py 设置加载模型的路径修改启动代码: demo.queue().launch(shareFalse…...
C++对象模型
思考:对于实现平面一个点的参数化。C的class封装看起来比C的struct更加的复杂,是否意味着产生更多的开销呢? 实际上并没有,类的封装不会产生额外的开销,其实,C中在布局以及存取上的额外开销是virtual引起的…...
Linux Framebuffer驱动框架、接口实现和使用
Linux 驱动-Frame Buffer代码分析 Framebufferfbmem.c部分代码分析初始化 Framebuffer 对于驱动开发人员来说,其实只需要针对具体的硬件平台SOC和具体的LCD(通过焊接连接到该SOC引脚上的LCD)来进行第一部分的寄存器编程(红色部分&…...
AI:54-基于深度学习的树木种类识别
🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…...
MVCC详解
什么是MVCC? MVCC,即Multi-Version Concurrency Control (多版本并发控制)。它是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 通俗的讲&am…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
