观察者模式实战:解密最热门的设计模式之一

文章目录

  • 前言
  • 一、什么是观察者模式
  • 二、Java实现观察者模式
    • 2.1 观察者接口
    • 2.2 具体观察者
    • 2.3 基础发布者
    • 2.4 具体发布者
    • 2.5 消息发送
  • 三、Spring实现观察者模式
    • 3.1 定义事件类
    • 3.2 具体观察者
    • 3.3 具体发布者
    • 3.4 消息发送
  • 总结

前言

随着系统的复杂度变高,我们就会采取各种各样的优化手段来进行解耦,降低系统的复杂度,其中设计模式是古人经验的一种设计总结,场景一:发送消息的时候,需要采取不同的消息发送渠道,一次发送一个或者多个渠道,这种不确定的变化,我们就可以采用观察者模式来进行解耦,当一个对象状态发生改变时,其他依赖对象的状态也随之变更,这是观察者模式的核心。

注:本篇文章纯干货,采用Java的设计模式以及Spring设计模式实现,另外设计编码了交互页面,能够更直观体验观察者模式之美

一、什么是观察者模式

观察者模式是一种行为设计模式,类似于【发布订阅】,定义对象间的一种【一对多】的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

二、Java实现观察者模式

2.1 观察者接口

/**
 * 监听(观察者)接口
 * @author: DT辰白 Created by 2024/5/3 8:09
 */
public interface EventListener {

    void update(String message);

}

2.2 具体观察者

/**
 * 具体观察者
 * @author: DT辰白 Created by 2024/4/28 20:12
 */
@Slf4j
@Service
public class EmailListener implements EventListener {

    @Override
    public void update(String message) {
        log.info("邮箱:QQ邮箱发送消息,消息内容【{}】",message);
    }
}
/**
 * 具体观察者
 * @author: DT辰白 Created by 2024/4/28 20:14
 */
@Slf4j
@Service
public class SmsListener implements EventListener {

    @Override
    public void update(String message) {
        log.info("短信:短信发送消息,消息内容【{}】", message);
    }
}

2.3 基础发布者

这里我们使用了@Autowired注入,其实默认的实现类【EmailListener 、SmsListener】已经注入了,你也可以将List 做成一个普通的List集合,然后在使用的时候,将订阅对象添加到该List集合。

/**
 * @author: DT辰白 Created by 2024/4/28 20:17
 */
@Component
public class EventManager {

    @Autowired
    private List<EventListener> listeners;

    /**
     * 订阅
     * @param eventListeners
     */
    public void subscribe(EventListener... eventListeners) {
        for (EventListener eventListener : eventListeners) {
        	// 防止重复注入
            if (!listeners.contains(eventListener)) {
                this.listeners.add(eventListener);
            }
        }
    }

    /**
     * 取消订阅
     * @param eventListeners
     */
    public void unsubscribe(EventListener... eventListeners) {
        for (EventListener eventListener : eventListeners) {
            listeners.remove(eventListener);
        }
    }

    /**
     * 通知
     * @param message
     */
    public void notify(String message) {
        for (EventListener eventListener : listeners) {
            eventListener.update(message);
        }
    }
}

2.4 具体发布者

这里我们直接继承父类,可以通过子类调用父类的方法,我们也可以将此处做成一个抽象接口对外提供,具体方法有很多,根据自己的业务需求即可。

/**
 * 具体发布者
 * @author: DT辰白 Created by 2024/4/28 20:25
 */
@Service
public class MessagePublisher extends EventManager {

    public void publishMessage(String message) {
        notify(message);
    }

}

2.5 消息发送

@PostMapping(value = "/publishMessage")
@ApiOperation(value = "观察者模式【java】->发送消息")
public ResultUtil publishMessage(String message) {
    // 订阅(默认订阅全部)
    // messagePublisher.subscribe(emailListener,smsListener);
    // 取消订阅
    // messagePublisher.unsubscribe(smsListener);
    // 发布
    messagePublisher.publishMessage(message);
    return ResultUtil.success();
}
2024-05-03 08:25:17.049  INFO 12896 --- [nio-9091-exec-4] c.d.m.d.pattern.observer.EmailListener   : 邮箱:QQ邮箱发送消息,消息内容【我是一条鱼】
2024-05-03 08:25:17.049  INFO 12896 --- [nio-9091-exec-4] c.d.m.d.pattern.observer.SmsListener     : 短信:短信发送消息,消息内容【我是一条鱼】

三、Spring实现观察者模式

3.1 定义事件类

/**
 * 定义事件类
 * @author: DT辰白 Created by 2024/4/28 21:33
 */
public class NotificationEvent extends ApplicationEvent {

    private String message;

    public NotificationEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

3.2 具体观察者

/**
 * @author: DT辰白 Created by 2024/4/28 21:34
 */
@Slf4j
@Component
public class EmailNotificationListener {
    @EventListener
    public void onApplicationEvent(NotificationEvent event) {
        // 发送邮件通知
        log.info("邮箱:QQ邮箱发送消息,消息内容【{}】",event.getMessage());
    }
}
/**
 * @author: DT辰白 Created by 2024/4/28 21:34
 */
@Slf4j
@Component
public class SMSNotificationListener {
    @EventListener
    public void onApplicationEvent(NotificationEvent event) {
        // 发送短信通知
        log.info("短信:短信发送消息,消息内容【{}】", event.getMessage());
    }
}

3.3 具体发布者

/**
 * 发布者接口
 * @author: DT辰白 Created by 2024/4/28 21:35
 */
public interface NotificationService {

    void notifyUsers(String message);
}
/**
 * 事件发布者
 * @author: DT辰白 Created by 2024/4/28 21:35
 */
@Service
public class NotificationPublisher implements NotificationService {

    @Autowired
    private ApplicationEventPublisher publisher;

    @Override
    public void notifyUsers(String message) {
        publisher.publishEvent(new NotificationEvent(this, message));
    }
}

3.4 消息发送

@PostMapping(value = "/publishMsg")
@ApiOperation(value = "观察者模式【spring】->发送消息")
public ResultUtil publishMsg(String message) {
    notificationService.notifyUsers(message);
    return ResultUtil.success();
}
2024-05-03 10:39:14.302  INFO 12680 --- [nio-9091-exec-3] c.d.m.d.p.o.s.EmailNotificationListener  : 邮箱:QQ邮箱发送消息,消息内容【我是一条鱼】
2024-05-03 10:39:14.302  INFO 12680 --- [nio-9091-exec-3] c.d.m.d.p.o.s.SMSNotificationListener    : 短信:短信发送消息,消息内容【我是一条鱼】

以上方式为同步发送,如果不需要保证数据一致性,只要其中一个渠道消息发送成功即可,我们可以采用异步的方式发送,这样就不会影响其它正常的渠道发送,当然也是我们项目中常用的方式,发送失败的渠道,采用补偿机制或者人工介入重新发送即可,当然实际项目开发中,这种方式比较。
在这里插入图片描述
最后,为了更直观的体验观察者模式,我们设计了一个交互页面:

在这里插入图片描述

总结

观察者模式是一种行为设计模式,定义了一种一对多的依赖关系,当一个对象状态发生变化时,所有依赖它的对象都会得到通知并自动更新。Spring中的事件驱动模型就是观察者模式的典型应用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电商独立站最重要的功能设置:多语言转换和代运系统搭建

什么是独立站&#xff1f; 多语言模式切换 1 搭建电商独立站在我看来最简单的理解&#xff0c;就是独立的网站。 如果你在跨境圈子呆了一段时间&#xff0c;独立站是一个避不开且火热的一个词&#xff0c;并且也是所有的B2B、B2C商家都在运营和布局的市场。 独立站的优势有哪…

AI视频教程下载:零代码创建AI智能体、AI Agents和ChatGPT的Gpts

这门课程专注于提示工程的掌握&#xff0c;教你以精确的方式引导GPT&#xff0c;利用它们的生成能力产生卓越的AI驱动结果。一步一步地&#xff0c;你将学会创建多样化的GPT军团——每个都设计来满足特定的专业需求。 从提供个性化职业变更指导的职业教练AI&#xff0c;到以惊…

精准测试-Vue前端调用链影响变更分析之一

Vue前端调用链影响变更分析之一 一、背景二、工具调研1、 工具介绍&#xff1a;2、工具使用 三、工具落地集成方案&#xff08;待后续补充&#xff09;变更影响较为简单的实现变更影响较为复杂的实现1、全局关系数据库的构建2、变更影响的简单实现3、变更影响的复杂实现 一、背…

【LinuxC语言】系统日志

文章目录 前言一、系统日志的介绍二、向系统日志写入日志信息三、示例代码总结 前言 在Linux系统中&#xff0c;系统日志对于监控和排查系统问题至关重要。它记录了系统的运行状态、各种事件和错误信息&#xff0c;帮助系统管理员和开发人员追踪问题、进行故障排除以及优化系统…

(Microsoft SQL Server,错误: 233)

错误信息: A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程。) (Microsoft SQL Server&#xff0c;错误: 233) 原因&…

《十三》QT绘图原理双缓冲机制

一、原理与设计 所谓双缓冲机制&#xff0c;是指在绘制控件时&#xff0c;首先将要绘制的内容绘制在一个图片中&#xff0c;再将图片一次性地绘制到控件上。在早期的 Qt 版本中&#xff0c;若直接在控件上进行绘制工作&#xff0c;则在控件重绘时会产生闪烁地现象&#xff0c;控…

零基础学习数据库SQL语句之定义数据库对象的DDL语句

DDL语句 DDL Date Definition Language 数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库&#xff0c;表&#xff0c;字段&#xff09; 基本操作 数据库操作 查询所有数据库 SHOW DATEBASES查询当前数据库 SELECT DATEBASE() 创建 CREATE DATEBASE [IF …

利用大语言模型(KIMI)构建智能产品的控制信息模型

数字化的核心是数字化建模&#xff0c;为一个事物构建数字模型是一项十分复杂的工作。不同的应用场景&#xff0c;对事物的关注重点的不同的。例如&#xff0c;对于一个智能传感器而言&#xff0c;从商业的角度看&#xff0c;产品的信息模型中应该包括产品的类型&#xff0c;名…

Mysql的关联查询以及语句

一、mysql的连接查询 1、等值连接 这里是三张表的等值连接 select rp.role_id,rp.permission_id from role_permission rp, role r, permission p where rp.role_idr.id and rp.permission_idp.id 2、内连接&#xff1a; 角色&#xff1a;系统管理员 是否拥有权限&#xf…

DHCPv4_CLIENT_ALLOCATING_03: 发送DHCPREQUEST - 必须包含‘服务器标识符‘

测试目的&#xff1a; 验证客户端发送的DHCPREQUEST消息中是否包含“服务器标识符”选项&#xff0c;以指示它选择的服务器。 描述&#xff1a; 本测试用例旨在确保DHCP客户端在广播DHCPREQUEST消息时&#xff0c;必须包含“服务器标识符”选项。该选项用于指明客户端选择了…

2024-5-1我把QQ群聊天记录分析工具重写了一下

【下载地址】 https://www.lanzoub.com/b00rn0g47e 密码:9hww 【项目背景】 2020年我用Tkinter写过一个QQ群聊天记录分析的工具exe&#xff0c;后续也写过一个纯JS前端的版本&#xff0c;前阵子有个用户反馈不能用了&#xff0c;顺便看能不能加入一个分析关键词的功能&…

第76天:WAF攻防-信息收集识别被动探针代理池仿指纹白名单

目录 基础知识 案例一: 信息收集-被动扫描-黑暗引擎&三方接口 案例二: 信息收集-目录扫描-Python 代理加载脚本 案例三: 信息收集-爬虫扫描-Awvs&Xray&Goby内置 基础知识 什么是 WAF &#xff1f; Web Application Firewall &#xff08; web 应用防火墙&am…

jvm垃圾回收机制介绍

JVM&#xff08;Java虚拟机&#xff09;是Java程序的运行环境&#xff0c;它负责执行字节码文件。JVM的工作原理主要包括以下几个部分&#xff1a;类加载器、执行引擎、垃圾收集器和内存管理。类加载器负责加载字节码文件并将其转换成Java平台上的机器码&#xff0c;执行引擎负…

三维图形学知识分享---求平面与模型相交线

在CGAL&#xff08;Computational Geometry Algorithms Library&#xff09;中&#xff0c;Polygon_mesh_processing模块提供了用于处理多边形网格数据结构的功能。其中&#xff0c;surface_intersection函数是用来计算模型的表面相交线的工具。 CGAL_Mesh mesh_orcl;std::vect…

容器组_生命周期

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列、spring教程等&#xff0c;大家有兴趣的可以看一看 &#x1f4d9;Jav…

张大哥笔记:如何选择项目和未来发展方向,实现10倍增长

在过去的10年里&#xff0c;我加入了众多社群&#xff0c;接触了不少行业精英&#xff0c;还参与了各式各样的交流圈。这段时间&#xff0c;我一直在考虑一个问题&#xff1a;未来的发展道路究竟在何方&#xff1f;起初我认为只有那些具有长期积累价值的事业才有真正的前景&…

傅里叶变换理论2

1. 逆变换 2. 时间域和频率域 3. 波的基本单位

C语言例题29:在屏幕上显示一个等腰三角形

#include <stdio.h>void main() {int i, j;int x;printf("输入等腰三角形行数&#xff1a;");scanf("%d", &x);for (i 1; i < x; i) {for (j i; j < x; j) {printf(" "); //输出空格占位}for (j 1; j < 2 * i; j) {printf…

【计算机毕业设计】基于SpringBoot+Vue企业车辆管理系统设计与实现

目录 一、项目介绍 二、项目主要技术 三、系统体系结构 四、系统实现 五、实现代码 一、项目介绍 本系统采用Mysql数据库和java语言&#xff0c;SpringBoot框架进行开发而成&#xff0c;极大程度上的保证了系统的稳定性。管理人员可以管理个人中心、驾驶员管理、用户管…

FR-TSN4206获得“时间敏感网络产业链名录计划”测试认证证书,TSN交换机助力智能工业发展

TSN技术&#xff0c;即时间敏感网络技术&#xff0c;已成为智能工业、自动驾驶等领域的核心。它通过时钟同步、数据调度等功能&#xff0c;确保低延迟、高可靠性的数据传输。 为推动TSN技术在我国的发展&#xff0c;工业互联网产业联盟联合多家单位启动了“时间敏感网络产业链名…