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

news/2024/9/24 6:59:35/

文章目录

  • 前言
  • 一、什么是观察者模式
  • 二、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 观察者接口

java">/*** 监听(观察者)接口* @author: DT辰白 Created by 2024/5/3 8:09*/
public interface EventListener {void update(String message);}

2.2 具体观察者

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

2.3 基础发布者

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

java">/*** @author: DT辰白 Created by 2024/4/28 20:17*/
@Component
public class EventManager {@Autowiredprivate 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 具体发布者

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

java">/*** 具体发布者* @author: DT辰白 Created by 2024/4/28 20:25*/
@Service
public class MessagePublisher extends EventManager {public void publishMessage(String message) {notify(message);}}

2.5 消息发送

java">@PostMapping(value = "/publishMessage")
@ApiOperation(value = "观察者模式java】->发送消息")
public ResultUtil publishMessage(String message) {// 订阅(默认订阅全部)// messagePublisher.subscribe(emailListener,smsListener);// 取消订阅// messagePublisher.unsubscribe(smsListener);// 发布messagePublisher.publishMessage(message);return ResultUtil.success();
}
java">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 定义事件类

java">/*** 定义事件类* @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 具体观察者

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

3.3 具体发布者

java">/*** 发布者接口* @author: DT辰白 Created by 2024/4/28 21:35*/
public interface NotificationService {void notifyUsers(String message);
}
java">/*** 事件发布者* @author: DT辰白 Created by 2024/4/28 21:35*/
@Service
public class NotificationPublisher implements NotificationService {@Autowiredprivate ApplicationEventPublisher publisher;@Overridepublic void notifyUsers(String message) {publisher.publishEvent(new NotificationEvent(this, message));}
}

3.4 消息发送

java">@PostMapping(value = "/publishMsg")
@ApiOperation(value = "观察者模式【spring】->发送消息")
public ResultUtil publishMsg(String message) {notificationService.notifyUsers(message);return ResultUtil.success();
}
java">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中的事件驱动模型就是观察者模式的典型应用。


http://www.ppmy.cn/news/1450845.html

相关文章

Java中的流(Stream)以及它们在集合操作中的作用和例子

Java中的流&#xff08;Stream&#xff09;是Java 8引入的一个新特性&#xff0c;主要用于处理集合数据。流提供了一种声明式的方式来处理数据&#xff0c;使代码更加简洁和易于理解。通过使用流&#xff0c;你可以对集合数据进行各种复杂的操作&#xff0c;如过滤、映射、排序…

RocketMq详解:一、RocketMQ 介绍及基本概念

文章目录 前言1.RocketMQ简介2.RocketMQ 特点3.核心特性4.应用场景5.RocketMQ 优势6.RocketMQ 四大核心组件6.1 NameServer1.NameServer作用2.NameServer被设计为无状态的原因3.和NameServer和Zookeeper的区别4.NameServer的高可用保障 6.2 Broker1.Broker部署方式2.高可用与负…

[华为OD] C卷 服务器cpu交换 现有两组服务器QA和B,每组有多个算力不同的CPU 100

题目&#xff1a; 现有两组服务器QA和B,每组有多个算力不同的CPU,其中A[i]是A组第i个CPU的运算能 力&#xff0c;B[i]是B组第i个CPU的运算能力。一组服务器的总算力是各CPU的算力之和。 为了让两组服务器的算力相等&#xff0c;允许从每组各选出一个CPU进行一次交换。 求两…

蓝桥杯练习系统(算法训练)ALGO-950 逆序数奇偶

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 老虎moreD是一个勤于思考的青年&#xff0c;线性代数行列式时&#xff0c;其定义中提到了逆序数这一概念。不过众所周知我们…

3D看车有哪些强大的功能?适合哪些企业使用?

3D看车是一种创新的汽车展示方式&#xff0c;它提供了许多强大的功能&#xff0c;特别适合汽车行业的企业使用。 3D看车可实现哪些功能&#xff1f; 1、细节展示&#xff1a; 51建模网提供全套汽车行业3D数字化解决方案&#xff0c;3D看车能够将汽车展示得更加栩栩如生&…

axios.get请求 重复键问题??

封装的接口方法&#xff1a; 数据&#xff1a; 多选框多选后 能得到对应的数组 但是请求的载荷却是这样的,导致会请求不到数据 departmentChecks 的格式看起来是一个数组&#xff0c;但是通常 HTTP 请求的查询参数不支持使用相同的键&#xff08;key&#xff09;名多次。如…

pytorch-解决过拟合之early stop和dropout

目录 1. Early Stop2. 怎样Early Stop3. Dropout4. pytorch实现Dropout5. train和test时的Dropout6. 增加了vidom的示例代码 1. Early Stop 所谓的over fitting是训练集准确率在上升&#xff0c;但是test准确率开始下降了。 在测试集准确率达到最高点开始下降的时候停止训练&a…

Qt Creator中变量与函数的注释 - 鼠标悬浮可显示

Qt Creator中变量与函数的注释 - 鼠标悬浮可显示 引言一、变量注释二、函数注释三、参考链接 引言 代码注释在软件开发中起着至关重要的作用。它们不仅有助于开发者理解和维护代码&#xff0c;还能促进团队协作&#xff0c;提高代码的可读性和可维护性。适当的注释应该是简洁明…