写在前面的话
本篇文章继续介绍一下观察者模式,这个在日常工作中接触还是挺多的,但和发布订阅模式又有什么不同呢?
相关文章:
《程序猿之设计模式实战 · 策略模式》
《程序猿之设计模式实战 · 装饰者模式》
《程序猿之设计模式实战 · 池化思想》
基础介绍
观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件处理系统。
主要角色:
- 主题(Subject):被观察的对象,维护观察者的列表,并提供注册、注销观察者的方法。
- 观察者(Observer):对主题的变化感兴趣的对象,定义一个更新接口,以便接收主题的通知。
观察者模式的日常应用场景:
事件处理系统:如 GUI 应用中的按钮点击、文本框输入等事件的处理。
消息推送:社交媒体应用中,当用户发布新内容时,所有关注该用户的用户都会收到通知。
股票市场:当股票价格变化时,所有订阅该股票的投资者都会收到更新。
天气监测:天气预报应用中,用户可以订阅天气变化的通知。
日志系统:在日志框架中,多个观察者可以监听日志事件并执行相应的处理(如写入文件、发送邮件等)。
代码实现
Spring的事件用法就是典型的观察者模式。
实现步骤:
Step1、创建自定义事件
public class CustomEvent extends ApplicationEvent {
private String message;
public CustomEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
Step2、创建事件监听器
@Component
public class CustomEventListener {
@EventListener
public void handleCustomEvent(CustomEvent event) {
System.out.println("Received custom event - Message: " + event.getMessage());
}
}
Step3、创建事件发布者
@Component
public class EventPublisher {
private final ApplicationEventPublisher publisher;
public EventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void publish(String message) {
CustomEvent event = new CustomEvent(this, message);
publisher.publishEvent(event);
}
}
Step4、合适的位置触发一下事件,例如下方的服务初始化。
@Component
public class AppRunner implements CommandLineRunner {
private final EventPublisher eventPublisher;
@Autowired
public AppRunner(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Override
public void run(String... args) throws Exception {
eventPublisher.publish("Hello, Observer Pattern!");
}
}
观察者&发布订阅
观察者模式和发布-订阅模式(Publish-Subscribe Pattern)有相似之处,但它们之间也存在一些关键的区别:
1、耦合度:
观察者模式:主题和观察者之间是直接的依赖关系。观察者需要知道主题的存在,并注册到主题中。
发布-订阅模式:发布者和订阅者之间是解耦的。发布者不需要知道任何订阅者的存在,反之亦然。它们通过一个中介(如消息代理)进行通信。
2、通信方式:
观察者模式:通常是同步的,观察者在主题状态变化时立即收到通知。
发布-订阅模式:可以是同步或异步的,发布者发布消息后,订阅者可以在稍后时间接收消息。
3、使用场景:
观察者模式:适用于一对多的关系,通常在同一个应用程序中使用。
发布-订阅模式:适用于分布式系统或微服务架构,允许不同的应用程序或服务之间进行通信。
总结:
观察者模式和发布-订阅模式都用于实现事件驱动的架构,但它们在耦合度、通信方式和使用场景上有所不同。选择哪种模式取决于具体的需求和应用场景。
补充说明
按前面内容所介绍的,好像发布订阅模式的使用场景更广,比如 RedisTemplate.convertAndSend 方法在 Spring 中用于将消息发送到 Redis 的某个频道。这种机制可以被视为一种发布-订阅模式的实现,而不是严格的观察者模式。又比如Kafka 中的生产者和消费者的交互属于典型的发布-订阅模式。
这里再分析比对一下两者。
发布-订阅模式
使用场景:适用于需要在不同组件之间进行松耦合通信的场景。比如,使用 Redis、Kafka 等消息中间件时,发布者和订阅者之间没有直接的依赖关系。
优点:可以轻松扩展,添加新的订阅者不需要修改发布者的代码,适合分布式系统。
观察者模式
使用场景:通常用于对象之间的直接关系,适合在同一应用程序内部进行事件通知。Spring 的事件机制就是一个典型的例子。
优点:实现简单,适合在内存中处理事件,适合小范围的事件传播。
总结一下:
发布-订阅模式:适合跨服务或组件的通信,使用消息中间件。
观察者模式:适合在同一应用程序内部的事件处理,使用 Spring 的事件机制。
这两种模式各有其适用场景,选择时可以根据具体需求来决定。
总结陈词
还是那句话,不用过多的纠结在用的是哪个设计模式,实现的是什么标准。
遇到实际问题能使用合适的方式解决,同时代码经得起推敲和扩展,才是最主要的。
还是那句话,你可以不用,但不能不会。
💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。