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

【设计模式】【观察者模式】实例

一对多的统一监听 —— 这就是 观察者模式(Observer Pattern) 的经典应用场景。

也就是说:

  • 一个事件源(Subject) → 可以注册多个监听器(Observers);

  • 当事件发生时,一次性通知所有监听器

  • 各监听器通过统一的接口接收回调。


🔧 Java 示例代码

import java.util.ArrayList;
import java.util.List;// 统一监听接口(Observer)
interface EventListener {void onEvent(String event);
}// 事件源(Subject)
class EventSource {private final List<EventListener> listeners = new ArrayList<>();// 添加监听器public void addListener(EventListener listener) {listeners.add(listener);}// 移除监听器public void removeListener(EventListener listener) {listeners.remove(listener);}// 触发事件,通知所有监听器public void triggerEvent(String event) {System.out.println("EventSource: 触发事件 -> " + event);for (EventListener listener : listeners) {listener.onEvent(event);}}
}// 具体监听器 A
class LoggingListener implements EventListener {@Overridepublic void onEvent(String event) {System.out.println("LoggingListener 收到事件: " + event);}
}// 具体监听器 B
class AlertListener implements EventListener {@Overridepublic void onEvent(String event) {System.out.println("AlertListener 收到事件: " + event);}
}// 测试
public class ObserverPatternDemo {public static void main(String[] args) {EventSource source = new EventSource();// 注册多个监听器source.addListener(new LoggingListener());source.addListener(new AlertListener());source.addListener(event -> System.out.println("匿名Listener 收到事件: " + event));// 触发事件source.triggerEvent("用户登录");source.triggerEvent("文件上传");}
}

▶️ 输出结果

EventSource: 触发事件 -> 用户登录
LoggingListener 收到事件: 用户登录
AlertListener 收到事件: 用户登录
匿名Listener 收到事件: 用户登录EventSource: 触发事件 -> 文件上传
LoggingListener 收到事件: 文件上传
AlertListener 收到事件: 文件上传
匿名Listener 收到事件: 文件上传

📌 总结

  • 一对多的统一监听 就是 观察者模式

    • Subject(事件源):维护监听器集合;

    • Observer(监听器):实现统一回调接口;

    • Notify(通知):事件触发时,循环回调所有监听器。

这样做的好处是:

  • 解耦(事件源无需关心监听器的实现细节);

  • 扩展性好(随时新增/删除监听器);

  • 统一接口(所有监听器用一个回调方法 onEvent 处理)。

Android 里到处都是“一对多统一监听”这种观察者模式的实例,几乎是 核心设计思想之一。下面列几个典型的例子给你:


📌 Android 中的一对多统一监听实例

1. View 的点击事件分发

  • 事件源(Subject)View

  • 监听器(Observer)OnClickListener

  • 但这里是 一对一,只能设置一个 OnClickListener
    👉 不过在 事件总线/广播里是一对多。


2. BroadcastReceiver(广播机制)

这是 Android 里 最标准的一对多统一监听

  • 事件源:系统/应用发送的广播(Intent)。

  • 观察者:所有注册的 BroadcastReceiver

  • 当广播触发时,系统会依次通知所有匹配的接收者。

// 注册广播接收器
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {int level = intent.getIntExtra("level", 0);System.out.println("收到电量变化广播: level=" + level);}
}, filter);// 任意地方发广播
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.putExtra("level", 90);
sendBroadcast(intent);

👉 所有监听 ACTION_BATTERY_CHANGED 的接收器都会同时收到回调。


3. LiveData / Flow / RxJava

  • 事件源LiveData<T>

  • 观察者Observer<T>

  • 你可以给同一个 LiveData 添加多个观察者,它们会同时收到数据更新。

MutableLiveData<String> liveData = new MutableLiveData<>();// 监听器1
liveData.observe(this, data -> {Log.d("Observer1", "收到数据: " + data);
});// 监听器2
liveData.observe(this, data -> {Log.d("Observer2", "收到数据: " + data);
});// 触发事件
liveData.setValue("新消息来了!");

👉 输出:

Observer1: 收到数据: 新消息来了!
Observer2: 收到数据: 新消息来了!

4. RecyclerView.AdapterDataObserver

  • 事件源RecyclerView.Adapter

  • 观察者AdapterDataObserver

  • 当数据集变化时,会通知所有观察者(例如 RecyclerView 自己 + 其他订阅者)。

RecyclerView.Adapter adapter = ...;
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {@Overridepublic void onChanged() {Log.d("Observer", "Adapter 数据更新");}
});// 更新数据
adapter.notifyDataSetChanged();

5. ContentObserver

  • 事件源:ContentProvider 数据变化。

  • 观察者:所有注册的 ContentObserver

getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,true,new ContentObserver(new Handler()) {@Overridepublic void onChange(boolean selfChange) {Log.d("Observer", "相册数据变化了!");}}
);

✅ 总结

在 Android 里,一对多统一监听(观察者模式)的典型实现有:

  1. BroadcastReceiver(广播机制)

  2. LiveData.observe()

  3. RecyclerView.AdapterDataObserver

  4. ContentObserver

  5. EventBus/Flow/RxJava

这些都属于 统一监听回调的一对多场景


Android 开发里,观察者模式(Observer Pattern)非常常见,主要用于 “一对多”通知的场景:当一个对象(被观察者/Subject)状态变化时,会自动通知所有依赖它的对象(观察者/Observer),从而实现解耦。


🔹 为什么要用观察者模式?

  1. 解耦合:观察者不需要知道被观察者的内部实现,只关心变化。

  2. 灵活扩展:可以随时增加/移除观察者,不需要修改被观察者逻辑。

  3. 统一通知机制:避免手动在多个地方写重复的刷新或回调。


🔹 在 Android 中常见的使用场景

1. UI 更新和数据监听

  • LiveData + Observer(Jetpack):UI 组件(Activity/Fragment)订阅数据,数据变化时自动刷新 UI。

  • EventBus/RxJava:跨组件事件传递,类似全局观察者模式。

2. 自定义组件封装

例如封装一个 网络状态监听组件

  • 被观察者:NetworkManager(内部监听系统广播/ConnectivityManager)。

  • 观察者:Activity/Fragment/自定义 View,需要知道网络是否可用。

这样多个页面只要注册为观察者,就能统一收到网络变化通知。

3. 多模块通信

  • 下载/上传进度监听:下载器作为 Subject,UI 页面作为 Observer。

  • 播放器状态监听:MediaPlayer/ExoPlayer 的状态变化通知给 UI 控件(进度条、播放按钮)。

4. 数据缓存和刷新

比如 Room + LiveData 就是典型观察者模式:数据库数据变更 → LiveData 通知 → UI 自动刷新。


🔹 简单封装示例

假设我们封装一个 全局事件中心,支持任意组件监听和通知。

// 1. 定义观察者接口
public interface Observer<T> {void onUpdate(T data);
}// 2. 被观察者(事件中心)
public class EventBus<T> {private final List<Observer<T>> observers = new ArrayList<>();public void register(Observer<T> observer) {observers.add(observer);}public void unregister(Observer<T> observer) {observers.remove(observer);}public void notifyObservers(T data) {for (Observer<T> observer : observers) {observer.onUpdate(data);}}
}// 3. 使用示例
public class NetworkManager {private static final EventBus<Boolean> eventBus = new EventBus<>();public static void addNetworkObserver(Observer<Boolean> observer) {eventBus.register(observer);}public static void removeNetworkObserver(Observer<Boolean> observer) {eventBus.unregister(observer);}// 系统监听到网络变化时调用public static void onNetworkChanged(boolean available) {eventBus.notifyObservers(available);}
}

在 Activity 中用法:

public class MainActivity extends AppCompatActivity {private final Observer<Boolean> networkObserver = available -> {Toast.makeText(this, available ? "网络可用" : "网络不可用", Toast.LENGTH_SHORT).show();};@Overrideprotected void onStart() {super.onStart();NetworkManager.addNetworkObserver(networkObserver);}@Overrideprotected void onStop() {super.onStop();NetworkManager.removeNetworkObserver(networkObserver);}
}

这样就实现了一个简单的观察者封装:

  • 解耦:NetworkManager 不关心谁在监听。

  • 可复用:任意页面都能监听网络变化。


🔹 总结

在 Android 里,观察者模式适用于:

  • 数据驱动 UI(LiveData、Flow、RxJava)

  • 组件通信(EventBus、全局状态监听)

  • 自定义控件封装(播放器、下载器、网络监控等)

👉 适合所有 “一个地方变化,多个地方要响应” 的场景。


文章转载自:

http://yqCfIee0.bppmL.cn
http://SSQkEKFy.bppmL.cn
http://ULmMGPPq.bppmL.cn
http://HSqCdnin.bppmL.cn
http://5s0yPa9C.bppmL.cn
http://vaTMDOlq.bppmL.cn
http://nSH8k02q.bppmL.cn
http://GL6fuJ2q.bppmL.cn
http://z5cm4JW4.bppmL.cn
http://PBw5lOie.bppmL.cn
http://reDeAGo6.bppmL.cn
http://2BAxUA3l.bppmL.cn
http://vssunwJJ.bppmL.cn
http://9dinkC0r.bppmL.cn
http://w9VguquF.bppmL.cn
http://tNdxXlWs.bppmL.cn
http://KNySFsNS.bppmL.cn
http://IMSqs1eK.bppmL.cn
http://lOUqfBzA.bppmL.cn
http://N0CczjdS.bppmL.cn
http://BCIXBHxH.bppmL.cn
http://gIgrg83C.bppmL.cn
http://Z43xfteG.bppmL.cn
http://Sr657DnD.bppmL.cn
http://VKI2qidw.bppmL.cn
http://gxjnZAiV.bppmL.cn
http://IDNsxmdu.bppmL.cn
http://6wdWWIlU.bppmL.cn
http://efc0IbB3.bppmL.cn
http://q1dUBjvA.bppmL.cn
http://www.dtcms.com/a/376512.html

相关文章:

  • 【Linux手册】消息队列从原理到模式:底层逻辑、接口实战与责任链模式的设计艺术
  • 学习React-10-useTransition
  • Hive中的3种虚拟列以及Hive如何进行条件判断
  • 基于 C++ 的 IEC60870-5-104 规约的主从站模拟数据通信
  • css flex布局,设置flex-wrap:wrap换行后,如何保证子节点被内容撑高后,每一行的子节点高度一致。
  • 一款免费开源轻量的漏洞情报系统 | 漏洞情报包含:组件漏洞 + 软件漏洞 + 系统漏洞
  • 容器问答题上
  • uniapp发布成 微信小程序 主包内 main.wxss 体积太大
  • Uniapp中使用renderjs实现OpenLayers+天地图的展示与操作
  • 鸿蒙HAP包解包、打包、签名及加固全流程解析
  • [Leetcode 算法题单] 1456. 定长子串中元音的最大数目
  • 基于Springboot + vue实现的高校大学生竞赛项目管理系统
  • 为什么 socket.io 客户端在浏览器能连上,但在 Node.js 中报错 transport close?
  • Windows 命令行:切换盘符
  • 论文阅读记录之《VelocityGPT 》
  • 微服务通信实战篇:基于 Feign 的远程调用与性能优化
  • “双轮”驱动见成效 中和农信深耕乡村“最后一百米”
  • 高防IP怎样抵御CC攻击的频繁侵扰?
  • LeetCode 面试经典 150_矩阵_生命游戏(38_289_C++_中等)(额外状态)
  • Kotlin 2.2.20 现已发布!下个版本的特性抢先看!
  • Shell编程:计算鸡兔同笼问题
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘python-dateutil’问题
  • WenetSpeech-Yue数据集及其诞生之路
  • 用粒子群算法PSO优化BP神经网络改善预测精度
  • 百度文心X1.1发布!实测深度思考能力!
  • 第六篇:终极压力测试——故障注入测试(FIT)
  • 文心大模型 X1.1:百度交出的“新深度思考”答卷
  • 物联网平台中的MongoDB(二)性能优化与生产监控
  • 性能测试-jmeter9-逻辑控制器、定时器压力并发
  • 网络编程;TCP控制机械臂;UDP文件传输;0910;ps今天没写出来