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

Java 内置观察者模式

Java 内置观察者模式

一、基础概念

观察者模式属于行为型设计模式,核心思想:
一对多依赖关系:一个目标(被观察者/主题)状态发生变化时,自动通知所有订阅它的观察者,观察者收到通知后执行自身更新逻辑,二者解耦。

Java 早期 JDK 直接提供了一套原生 API 实现观察者模式,位于java.util包下,由两个核心类/接口构成:

  1. java.util.Observable:被观察者(主题、发布者)抽象父类(类,非接口)
  2. java.util.Observer:观察者函数式接口

⚠️ 重要前提:Java 9 开始被标记为@Deprecated(过时废弃),官方不再推荐使用。

二、两大核心组件详解

1. Observer 观察者接口

@FunctionalInterfacepublicinterfaceObserver{/** * 被观察者状态变更,回调此方法通知观察者 * @param o 触发通知的被观察者对象 * @param arg 推送携带的自定义参数(可选) */voidupdate(Observableo,Objectarg);}
  • 函数式接口:可以直接用 Lambda 简写实现
  • 所有观察者必须实现该接口,重写update()接收消息推送

2. Observable 被观察者(主题)

是一个普通类,不能多继承,内部维护了观察者集合,提供订阅、取消订阅、状态变更通知全套方法:

核心成员变量
// 存放所有已订阅的观察者,线程安全容器privatefinalVector<Observer>obs;// 标记被观察者自身状态是否发生改变privatebooleanchanged=false;
常用核心方法
方法作用
void addObserver(Observer o)订阅:添加观察者到集合
void deleteObserver(Observer o)取消订阅:移除指定观察者
void deleteObservers()清空所有观察者
int countObservers()获取当前订阅的观察者数量
protected void setChanged()关键:标记自身状态已修改;只有标记后,才会执行通知
protected void clearChanged()清除状态变更标记
boolean hasChanged()查询是否标记了状态变更
void notifyObservers()无参推送:通知所有观察者,arg=null
void notifyObservers(Object arg)带参数推送:携带数据传给观察者update方法
通知执行流程
  1. 业务修改被观察者数据 → 调用setChanged()打上变更标记
  2. 调用notifyObservers()
  3. 内部遍历所有观察者,挨个调用observer.update(this, 参数)
  4. 通知完毕自动调用clearChanged()清空标记

三、完整代码示例(手把手演示)

场景:公众号(被观察者)发布文章,订阅用户(观察者)收到推送通知

importjava.util.Observable;importjava.util.Observer;// 1. 自定义被观察者:公众号classOfficialAccountextendsObservable{// 发布文章方法publicvoidpublishArticle(Stringcontent){System.out.println("公众号发布新文章:"+content);// 第一步:标记状态发生改变(必须调用!否则不会推送通知)setChanged();// 第二步:推送消息给所有订阅者,携带文章内容notifyObservers(content);}}// 2. 测试主类publicclassObserverDemo{publicstaticvoidmain(String[]args){// 创建被观察者OfficialAccountaccount=newOfficialAccount();// 观察者1:用户AObserveruserA=(obs,arg)->{System.out.println("用户A收到推送:新文章 -> "+arg);};// 观察者2:用户BObserveruserB=(obs,arg)->{System.out.println("用户B收到推送:新文章 -> "+arg);};// 订阅account.addObserver(userA);account.addObserver(userB);// 发布文章,触发通知account.publishArticle("Java观察者模式详解");System.out.println("=====用户B取消订阅后====");// 取消订阅account.deleteObserver(userB);account.publishArticle("Spring源码阅读笔记");}}

运行结果:

公众号发布新文章:Java观察者模式详解 用户B收到推送:新文章 -> Java观察者模式详解 用户A收到推送:新文章 -> Java观察者模式详解 =====用户B取消订阅后==== 公众号发布新文章:Spring源码阅读笔记 用户A收到推送:新文章 -> Spring源码阅读笔记

四、JDK内置实现的优缺点

优点

  1. 开箱即用,无需自己维护观察者集合、订阅/取消订阅、通知遍历逻辑,代码极简
  2. 自带状态变更标记机制,可灵活控制什么时候推送消息
  3. 自带线程安全(底层Vector),基础多线程场景不用自己加锁

致命缺点(也是被废弃的根本原因)

  1. Observable是类,不是接口,违反面向接口编程
    Java是单继承,如果你的业务类已经继承了其他父类,就无法再继承Observable,扩展性极差。

  2. 无法自定义通知顺序、通知策略
    内部遍历Vector有序推送,不能调整观察者回调顺序;同步阻塞推送,一个观察者耗时过长会阻塞后续所有观察者。

  3. 耦合度偏高
    被观察者、观察者都强依赖JDK util包内置类,不方便替换实现。

  4. 无法精细控制通知粒度
    只能全体推送,不支持按话题分组订阅(类似MQ的主题订阅)。

  5. 线程模型单一:默认同步调用,没有异步通知能力。

五、为什么 Java 9+ 废弃这套API?

  1. 设计缺陷:Observable作为具体类,继承限制太大,不符合开闭原则;
  2. 功能简陋:不支持异步、分组订阅、事件类型区分;
  3. 官方推荐替代方案:
    • 小型场景:自己手写观察者模式(自定义主题接口+观察者接口)
    • 企业级开发:使用事件驱动框架:Guava EventBus、Spring 事件监听(ApplicationEvent)、RxJava、消息队列(RabbitMQ/Kafka)

六、对比:手写观察者 vs JDK内置

  1. JDK内置:省事,但受继承约束、扩展性差;
  2. 手写自定义:自己定义Subject主题接口、Observer观察者接口,任意类都能实现,自由度最高,日常开发首选。

七、拓展:Spring中的事件监听(观察者模式最佳实践)

Spring框架基于观察者思想封装了事件机制,彻底规避了JDK原生的所有问题:

  • ApplicationEvent:事件(消息载体)
  • ApplicationEventPublisher:发布者(被观察者)
  • ApplicationListener:事件监听者(观察者)
    支持异步监听、条件监听、注解驱动(@EventListener),是Java后端最常用的观察者落地方案。
http://www.jsqmd.com/news/1292033/

相关文章:

  • SSM+Vue全栈果蔬商城开发实战
  • C++默认参数与引用传递:核心原理、组合陷阱与工程实践
  • Gitee CodePecker是什么:SAST、SCA与GraphAgent如何进入DevSecOps流程
  • FPGA设计核心:时空资源权衡与并行架构实践指南
  • 2026 年新消息:孝感口碑好的装饰雕塑订制厂家联系电话,放在玄关的这玩意儿,居然能让来访客人夸三个月,秘密在哪? - 实业推荐官【官方】
  • 【Go语言入门学习笔记】Part19.速率控制、原子计数器、互斥锁(Mutex)、状态协程
  • 51单片机按键计数与数码管显示:从硬件搭建到软件优化的嵌入式入门实战
  • Office效率革命:Alt+=快捷键解锁专业数学公式编辑
  • 深入理解JavaScript toString():从隐式转换到自定义对象序列化
  • Verilog硬件描述语言:从并发思维到可综合设计的FPGA开发指南
  • Qt 6.5安卓开发环境配置全攻略:从JDK、SDK到APK打包
  • SAP Fiori中Business Catalog引用机制详解与实践指南
  • KMS智能激活实战指南:三步永久激活Windows和Office的完整方案
  • 2026 年连江口碑好的村口大门坊门生产厂家哪家靠谱,拆掉它的3年里,村口人再也没有过跨进家门时那股热乎劲儿? - 领域鉴赏官
  • Keil RTE实战指南:STM32开发中的软件组件管理与配置
  • 电动车路径优化:MOPGA-NSGA-II算法与Matlab实现
  • 企业级AI应用落地:从Claude合作看工程化实践与个人开发指南
  • 首选:推荐浙江全屋高定厂家 - 品牌推广大师
  • 2026 年更新:北流专业的战争场景复原公司哪个好,那堆尘封的老物件,藏着怎样被改写的过往?-十指艺术场景 - 实业推荐官【官方】
  • STM32 OLED调试工具:分层框架设计与嵌入式开发实战
  • 16缓存16AXI系统架构:缓存一致性协议与AXI总线设计解析
  • 宁波催化燃烧RTO/RCO装置正规工厂分析推荐,滤筒除尘器/旋风分离器,催化燃烧RTO/RCO装置公司推荐分析 - 品牌推荐师
  • STM32工程搭建全解析:从Keil配置到标准库应用实战
  • SSM框架实战:水果电商系统设计与防超卖实现
  • 非常规日期格式解析与处理实践
  • 书本之外,皆是学问
  • 深入解析STM32内存模型:从Flash/RAM布局到堆栈管理实战
  • 从零实现Linux cat命令:深入理解文件描述符与系统调用
  • AI风控模型在反欺诈场景中的性能断崖式下滑(2024银保监新规下的7大隐性失效点)
  • 高密市防水补漏_2026山东东部莫言故里城市漏水维修流程教程与五大正规团队推荐 - 雨婺虹房屋维修