当前位置: 首页 > 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://www.jsqmd.com/news/73180/

相关文章:

  • 2025年东莞优质的铝门窗批发选哪家,安全门窗/铝门窗/慕莎尼奥门窗/窗纱一体铝门窗/门窗/铝门窗品牌选哪家 - 品牌推荐师
  • 2025年市面上排行前列的推拉窗厂家有哪些,侧压平移推拉窗/六轨断桥推拉窗/平移断桥提升窗/推拉窗源头厂家推荐排行榜 - 品牌推荐师
  • 详细介绍:Chrome HSTS(HTTP Strict Transport Security)
  • tmux使用教程
  • 2025年12月上海别墅装修,上海极简风装修,上海新中式装修公司权威推荐,设计实力与市场口碑深度解析 - 品牌鉴赏师
  • Python 编程实战 实用工具与库 — Django 项目结构简介 - 指南
  • 2025.12.11总结
  • 2025年短视频代运营口碑前十强,专业机构推荐,短视频代运营团队/小红书代运营/短视频代运营/企业号代运营短视频代运营系统选哪家 - 品牌推荐师
  • 124_尚硅谷_闭包的基本介绍
  • One Year XTOOL D9S Update Service: Keep Diagnostics Up-to-Date for EU US Vehicles
  • 如何确定arm固件的加载地址
  • 2025年数控车床品牌新格局,机械手集成能力排行揭晓,动力刀塔数控车/牙科配件数控车床/新能源数控车床/军工配件数控机床数控车床设计怎么选择 - 品牌推荐师
  • 2025年国内靠谱的门窗源头厂家推荐,全屋门窗/环保门窗/复古门窗/极简门窗/欧式门窗/智能门窗/门窗直销厂家找哪家 - 品牌推荐师
  • 2025军工智造基石:十大数控车床厂家权威评测排行,4轴数控机床/水暖接头数控机床/机械手数控车床/液冷接头数控机床数控车床门店怎么选择 - 品牌推荐师
  • 1-Year XTOOL D9 Update: Keep Diagnostics Current for EU US Vehicles
  • <<Learning visionbased agile flight via differentiable physics>>端到端无人机高速避障方案解析 - 教程
  • 2025年机械手数控车床品牌价格排行:前十名多少钱一台?英伟达液冷数控车/车铣复合数控机床/医疗器械数控机床数控车床采购排行榜 - 品牌推荐师
  • 聚焦2025:这些数控车床品牌是军工精密加工的保障,液冷接头数控机床/军工配件数控机床/空调配件数控机床/动力刀塔数控车数控车床批发排行 - 品牌推荐师
  • 2025年十大口碑小红书代运营公司深度解析,短视频运营公司/短视频代运营/抖音运营公司/抖音代运营/企业号代运营小红书代运营品牌推荐 - 品牌推荐师
  • 基于协同过滤推荐算法的求职招聘推荐系统u1ydn3f4(程序、源码、数据库、调试部署优秀的方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
  • 中国人工智能学会推荐国际学术会议和国际/国内期刊目录
  • 12.11笔记
  • 蓝桥杯-Python-题目整理2
  • Spring
  • 2025年机械手数控车床品牌排行揭晓,这些品牌领跑市场!英伟达液冷数控车/无人机配件数控/双主轴数控车床/4轴数控机床数控车床设计品牌 - 品牌推荐师
  • 【笔记】队列
  • ZROJ 3272. 地皮
  • Conda 常用命令总结01
  • 广州文辰入驻博客园:不搞虚的,只聊中小企业用得上的实操
  • 英语_错题集_时态