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

观察者模式

观察者模式:解耦依赖的事件响应机制

一、观察者模式的核心定义

观察者模式(Observer Pattern) 是一种行为型设计模式,定义了对象之间的一对多依赖关系:当一个对象(被观察者 / 主题)的状态发生变化时,所有依赖它的对象(观察者)都会自动收到通知并进行更新。这种模式的核心是解耦被观察者与观察者,让两者无需知晓对方的具体实现,仅通过统一的接口交互。

简单来说,观察者模式就像 “订阅 - 通知” 机制:比如公众号(被观察者)发布新文章时,所有关注该公众号的用户(观察者)都会收到推送,用户无需主动刷新,公众号也无需单独联系每个用户。

二、核心角色与结构

观察者模式包含四个核心角色,各角色职责明确,通过接口实现解耦:

  1. 抽象主题(Subject):定义被观察者的核心行为,包括注册观察者、移除观察者、通知所有观察者的接口。

  2. 具体主题(Concrete Subject):抽象主题的实现类,维护观察者列表,当自身状态变化时,调用通知方法触发所有观察者更新。

  3. 抽象观察者(Observer):定义观察者的更新接口,包含一个接收通知并处理的方法(如 update())。

  4. 具体观察者(Concrete Observer):抽象观察者的实现类,实现更新接口,根据被观察者的通知执行具体业务逻辑。

结构示意图(简化):

[具体主题] ← 注册/移除 → [抽象观察者]↑                          ↓通知                      实现↓                          ↑[具体观察者1]、[具体观察者2]、...

三、代码实现示例(Java)

以 “气象站发布天气数据,多个显示终端接收更新” 为例,实现观察者模式:

1. 抽象主题(Subject)

public interface WeatherSubject {// 注册观察者void registerObserver(WeatherObserver observer);// 移除观察者void removeObserver(WeatherObserver observer);// 通知所有观察者void notifyObservers();}

2. 具体主题(Concrete Subject)

import java.util.ArrayList;import java.util.List;public class WeatherData implements WeatherSubject {// 维护观察者列表private List observers;// 被观察的状态(温度、湿度、气压)private float temperature;private float humidity;private float pressure;public WeatherData() {observers = new ArrayList<>();}// 注册观察者@Overridepublic void registerObserver(WeatherObserver observer) {observers.add(observer);}// 移除观察者@Overridepublic void removeObserver(WeatherObserver observer) {observers.remove(observer);}// 通知所有观察者(状态变化时调用)@Overridepublic void notifyObservers() {for (WeatherObserver observer : observers) {// 传递最新状态,触发观察者更新observer.update(temperature, humidity, pressure);}}// 模拟气象站更新数据(实际场景中可能是传感器采集)public void setWeatherData(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;// 数据更新后,自动通知观察者notifyObservers();}}

3. 抽象观察者(Observer)

public interface WeatherObserver {// 接收通知并更新(参数为被观察者的最新状态)void update(float temperature, float humidity, float pressure);}

4. 具体观察者(Concrete Observer)

// 手机APP显示终端public class PhoneDisplay implements WeatherObserver {@Overridepublic void update(float temperature, float humidity, float pressure) {System.out.println("手机APP收到天气更新:");System.out.printf("温度:%.1f℃,湿度:%.1f%%,气压:%.1f hPa%n",temperature, humidity, pressure);}}// 电视天气预报终端public class TVDisplay implements WeatherObserver {@Overridepublic void update(float temperature, float humidity, float pressure) {System.out.println("n电视天气预报更新:");System.out.printf("今日气温:%.1f℃,空气湿度:%.1f%%,气压稳定在%.1f hPa%n",temperature, humidity, pressure);}}

5. 测试代码

public class ObserverTest {public static void main(String[] args) {// 创建被观察者(气象站)WeatherData weatherData = new WeatherData();// 创建观察者(显示终端)WeatherObserver phoneDisplay = new PhoneDisplay();WeatherObserver tvDisplay = new TVDisplay();// 注册观察者weatherData.registerObserver(phoneDisplay);weatherData.registerObserver(tvDisplay);// 模拟气象站更新数据System.out.println("=== 第一次更新天气数据 ===");weatherData.setWeatherData(25.5f, 60.2f, 1013.2f);System.out.println("n=== 第二次更新天气数据 ===");weatherData.setWeatherData(27.8f, 55.0f, 1012.5f);// 移除手机APP观察者weatherData.removeObserver(phoneDisplay);System.out.println("n=== 第三次更新天气数据(已移除手机APP) ===");weatherData.setWeatherData(23.1f, 70.5f, 1014.0f);}}

输出结果

=== 第一次更新天气数据 ===手机APP收到天气更新:温度:25.5℃,湿度:60.2%,气压:1013.2 hPa电视天气预报更新:今日气温:25.5℃,空气湿度:60.2%,气压稳定在1013.2 hPa=== 第二次更新天气数据 ===手机APP收到天气更新:温度:27.8℃,湿度:55.0%,气压:1012.5 hPa电视天气预报更新:今日气温:27.8℃,空气湿度:55.0%,气压稳定在1012.5 hPa=== 第三次更新天气数据(已移除手机APP) ===电视天气预报更新:今日气温:23.1℃,空气湿度:70.5%,气压稳定在1014.0 hPa

四、适用场景

观察者模式适用于以下场景:

  1. 对象间存在一对多依赖:一个对象状态变化需要联动多个对象响应(如:电商订单支付成功后,通知库存扣减、物流创建、积分增加)。

  2. 需要解耦依赖关系:避免被观察者与观察者直接耦合(如:消息队列的生产者 - 消费者模型,生产者无需知道消费者是谁)。

  3. 动态添加 / 移除观察者:需要灵活增减响应对象(如:网站的订阅功能,用户可随时关注 / 取消关注)。

五、优缺点分析

优点

  1. 解耦性强:被观察者与观察者通过接口交互,互不依赖具体实现,符合 “开闭原则”(新增观察者无需修改被观察者代码)。

  2. 响应及时:被观察者状态变化时,观察者自动收到通知,无需主动查询(“推模式” 高效)。

  3. 扩展性好:可随时添加新的观察者,或修改观察者的处理逻辑,不影响整体架构。

缺点

  1. 通知开销大:若观察者数量过多,被观察者通知所有观察者的过程会消耗较多资源,可能导致响应延迟。

  2. 循环依赖风险:若观察者与被观察者相互依赖,可能引发循环通知,导致系统崩溃。

  3. 顺序不可控:默认情况下,观察者的更新顺序由被观察者的通知顺序决定,若需指定顺序需额外处理。

六、扩展与变体

  1. 推模式 vs 拉模式
  • 推模式(本文示例):被观察者主动将状态数据推送给观察者,观察者被动接收。

  • 拉模式:被观察者仅通知 “状态已变”,观察者主动从被观察者获取所需数据(适合观察者需要不同状态的场景)。

  1. Java 内置支持:JDK 提供 java.util.Observable(抽象主题)和 java.util.Observer(抽象观察者),但因设计缺陷(如 Observable 是类而非接口,灵活性不足),实际开发中更推荐自定义接口实现。

  2. 结合其他模式:常与单例模式(确保被观察者唯一)、工厂模式(创建观察者实例)结合使用。

http://icebutterfly214.com/news/88148/

相关文章:

  • 2025年市面上排行前列的推拉窗厂家有哪些,侧压平移推拉窗/六轨断桥推拉窗/平移断桥提升窗/推拉窗源头厂家推荐排行榜 - 品牌推荐师
  • tmux使用教程
  • 2025年十大口碑小红书代运营公司深度解析,短视频运营公司/短视频代运营/抖音运营公司/抖音代运营/企业号代运营小红书代运营品牌推荐 - 品牌推荐师
  • 中国人工智能学会推荐国际学术会议和国际/国内期刊目录
  • 2025年机械手数控车床品牌排行揭晓,这些品牌领跑市场!英伟达液冷数控车/无人机配件数控/双主轴数控车床/4轴数控机床数控车床设计品牌 - 品牌推荐师
  • 10401_基于Springboot的植物园售票管理系统
  • LeeCode_4. 寻找两个正序数组的中位数
  • 记最近找的一款时间管理软件 - Higurashi
  • 持久化与内存管理策略——RDB/AOF、淘汰策略与容量规划的决策要点
  • 解码IPC-管道与信号 - 指南
  • 大夏龙雀DX-WF25(ESP32-C2-H2) mixly开发
  • MySQL基础语法复习笔记(含完整代码示例+新手实操指南) - 教程
  • FreeRTOS任务卡死在prvTaskExitError
  • 《程序员修炼之道:从小工到专家》笔记8
  • 2025年12月GEO服务商参考指南:聚焦豆包、DeepSeek,布局AI时代内容触达 - 品牌2025
  • 水刀切割机哪家好?2025热门切石机厂家权威排名汇总 - 栗子测评
  • 石材抛光机厂家哪家好?2025热门石材切割机厂家口碑推荐 - 栗子测评
  • 矿山机哪家好?2025靠谱矿山开采设备厂家排名推荐 - 栗子测评
  • 岩板切割机厂家推荐哪家?2025高性价比花岗岩切割机厂家排名 - 栗子测评
  • Meta闭源模型vocado、Google Gemini TTS情绪语音、微软智能体新高度
  • 全网热议!2025专业HIFI耳机口碑推荐,甄选5款优质耳机 - 讯息观点
  • QStyledItemDelegate
  • 2025年12月高压固态软启动柜厂家推荐:最新权威测评,技术力、规模化实测榜单 - AIEO
  • 2025年离心机国内知名厂家,离心机品牌排行推荐,离心机头部企业优质供应商,离心机有哪些厂 - 品牌推荐大师1
  • 可视化图解算法73:跳台阶(爬楼梯)
  • 北京十佳婚姻家事律师事务所服务特点及专业领域概述 - 品牌排行榜
  • 2025年12月薄膜精馏设备,实验室薄膜精馏设备,工业化薄膜精馏设备厂商推荐,低温分离技术与专利实力测评!​ - 品牌鉴赏师
  • 2025年评价高的陕西仿古铜瓦厂家最新权威推荐排行榜 - 朴素的承诺
  • 25 年度铜箔厂家口碑盘点:进口替代领先 + 全产业链布局(必看榜单) - 品牌排行榜
  • 日式搬家公司如何借GEO优化破局?AI搜索时代的新营销策略 - 博客万