【設計模式】【觀察者模式】實例

一對多的統一監聽 —— 這就是 觀察者模式(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://www.pswp.cn/bicheng/96633.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96633.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96633.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#測試調用OpenXml操作word文檔的基本用法

OpenXML SDK是微軟為高效處理Office文檔&#xff08;如Word、Excel&#xff09;而開發的開源.NET庫,它直接操作文檔內部的XML結構&#xff0c;無需安裝Office軟件即可實現文檔的創建、讀取和編輯,常用于服務器端批量生成報表、自動化文檔處理等場景&#xff0c;輕量且跨平臺。本…

照度傳感器考慮筆記

您好&#xff01;很高興為您解答關于照度計傳感器和設計的問題。這是一個非常專業且實際的話題。 一、照度計常用的照度傳感器類型 照度計的核心是光電探測器&#xff0c;其工作原理是將光信號轉換為電信號。目前主流的照度傳感器都屬于硅光電二極管&#xff08;Si Photodiode&…

C# Web API Mapster基本使用

安裝包&#xff1a;Mapster1.注冊MyRegister.Scan(); // 全局配置 //builder.Services.AddMapster(); // 需要安裝Mapster.DependencyInjection包 builder.Services.AddScoped<IMapper,Mapper>();2.配置&#xff08;可不進行配置直接使用也行&#xff09;public class My…

<數據集>無人機航拍人員搜救識別數據集<目標檢測>

數據集下載鏈接https://download.csdn.net/download/qq_53332949/91899456數據集格式&#xff1a;VOCYOLO格式 圖片數量&#xff1a;5755張 標注數量(xml文件個數)&#xff1a;5755 標注數量(txt文件個數)&#xff1a;5755 標注類別數&#xff1a;1 標注類別名稱&#xff…

STM32 開發(三十三)STM32F103 片內資源 —— 直接存儲 DMA 實戰 編碼詳解

??《上一篇》 ???《主目錄》 ???《下一篇》 文章目錄 一、基礎知識點 二、開發環境 三、STM32CubeMX相關配置 四、Vscode 代碼講解 ADC -DMA 采集溫度值 代碼解析 DAC -DMA 輸出 1KHZ 正弦波 代碼解析 五、結果演示 ADC -DMA 采集溫度值 結果演示 DAC -DMA 輸出 1KHZ 正…

Ip 地址,子網掩碼

1. 什么是 IP 地址&#xff1f;IP 地址是互聯網上設備的唯一標識&#xff0c;類似于現實中的“門牌號”&#xff0c;用于設備之間的通信。ABC類IP內網地址的范圍如下&#xff1a;A類地址&#xff1a;范圍是 10.0.0.0 到 10.255.255.255&#xff0c;用于大型網絡&#xff0c;網絡…

軟件工程領域內容運營的翻譯策略:打破語言邊界

軟件工程領域內容運營的翻譯策略:打破語言邊界 關鍵詞:軟件工程、內容運營、翻譯策略、技術本地化、術語管理、跨文化溝通、機器翻譯 摘要:在全球化協作日益緊密的今天,軟件工程領域的內容(如技術文檔、API手冊、開發者博客、開源社區指南等)早已突破單一語言限制,成為連…

元宇宙與金融創新:虛實融合下的金融服務新形態

1 元宇宙重構金融核心服務場景1.1 零售金融場景&#xff1a;從 “線下網點 線上 APP” 到 “沉浸式虛擬金融空間”傳統零售金融服務受限于物理網點或二維 APP&#xff0c;交互性與體驗感不足&#xff0c;元宇宙通過 “3D 虛擬金融空間 數字分身交互”&#xff0c;打造 “身臨…

信奧賽csp初賽高頻考點真題分類解析之:基本運算

信奧賽csp初賽高頻考點真題分類解析之:基本運算 ?題目1: 答案:C 題解:R進制轉換為十進制:按權展開 3 \times 8 1 ^1

PyTorch深度學習實戰【10】之神經網絡的損失函數

文章目錄零 回顧&#xff1a;機器學習中的模型訓練流程一 神經網絡的損失函數1.1 機器學習中的優化思想1.2 回歸&#xff1a;誤差平方和SSE1.3 二分類交叉熵損失的原理與實現1.3.1 極大似然估計求解二分類交叉熵損失1.3.2 實現二類交叉熵損失1.4 多分類交叉熵損失的原理與實現1…

人機協同中的層次映射關系研究:從自然語言處理到智能系統設計

一、引言&#xff1a;人機協同的層次化認知基礎人機協同作為人工智能領域的核心研究方向&#xff0c;正經歷從簡單工具使用到深度智能協作的范式轉變。在這一演進過程中&#xff0c;如何建立人類意圖與機器執行之間的有效映射關系成為關鍵挑戰。自然語言處理(NLP)領域中&#x…

2025主流大模型核心信息

2025主流大模型核心信息國際主流大模型1. GPT-5 (OpenAI)版本特性&#xff1a;多模態能力支持圖像、視頻、音頻的復雜理解與生成&#xff1b;超長上下文處理能力達1M tokens&#xff1b;推理能力接近專家水平優勢&#xff1a;綜合性能領先&#xff0c;編程能力強(SWE-bench Ver…

將容器連接到默認橋接網絡

1.列出當前已有的網絡[roothost1 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE db2f3a6af212 bridge bridge local 4251d9be020b host host local ba96ad98e029 none null local2.啟動兩個 ash &#xff08; Alpine 操作系…

安全審計-Ubuntu防火墻ufw

文章目錄 一、為什么運維需要使用防火墻? 二、Ubuntu 上常用的防火墻工具 三、UFW 常用命令及運維使用示例 1. 安裝 UFW(如果尚未安裝) 2. 查看防火墻狀態 3. 設置默認策略(強烈建議) 4. 允許必要服務(常見運維場景) ? 允許 SSH(遠程管理,最重要!) ? 允許 HTTP / …

iPhone 17系列包含哪些版本,各版本又有哪些配置,硬件、功能、性能、價格詳細介紹

文章目錄版本信息配置信息版本信息 iPhone 17系列提供了四個版本&#xff1a;iPhone 17 (標準版)、iPhone 17 Air、iPhone 17 Pro 和 iPhone 17 Pro Max。它們在設計、性能、影像等方面各有側重&#xff0c;下面是一個快速概覽表格&#xff0c;幫助你直觀了解它們的核心區別&a…

Go模塊自動導入教學文檔

目錄 概述核心概念實現原理項目結構代碼實現高級特性最佳實踐常見問題 概述 Go語言作為一門靜態類型語言&#xff0c;沒有像Python那樣的動態import機制。但是&#xff0c;我們可以通過設計模式和架構設計來實現"自動導入模塊"的功能。這種模式特別適合微服務架構…

深入解析Spring AOP核心原理

一 Spring-AOP1.對SpringAOP理解AOP是OOP的延續&#xff0c;是軟件開發中的一個熱點&#xff0c;也是Spring框架中的一個重要內容&#xff0c;是函數式編程的一種衍生泛型。利用AOP可以對業務邏輯的各個部分進行隔離&#xff0c;從而使得業務邏輯各部分之間的耦合度降低&#x…

大數據與AI:一場“數據盛宴”與“智能大腦”的奇妙邂逅

在當今這個信息爆炸的時代&#xff0c;大數據和AI&#xff08;人工智能&#xff09;就像一對熱戀中的情侶&#xff0c;天天黏在一起&#xff0c;形影不離。它們的結合&#xff0c;不僅改變了我們的生活方式&#xff0c;還讓這個世界變得更加有趣和奇妙。今天&#xff0c;就讓我…

解決window下共享資源報“不允許一個用戶使用一個以上用戶名與服務器或共享資源的多重連接“問題

問題現象&#xff1a; 使用不同samba共享賬號登錄同一服務器ip共享文件夾資源時會報錯誤提示解決辦法&#xff1a; 1.使用net use命令查看已保存的網絡連接 C:\Users\Administrator>net use 會記錄新的網絡連接。狀態 本地 遠程 網絡----…

SciKit-Learn 全面分析分類任務 wine 葡萄酒數據集

背景 wine 葡萄酒數據集&#xff0c;提供了對三種不同品種的意大利葡萄酒的化學分析結果 主要特點&#xff1a; 數據集規模&#xff1a;總共有 178 個樣本特征數量&#xff1a;每個樣本有 13 個化學特征&#xff0c;包括酒精、蘋果酸、灰分、鎂等類別數量&#xff1a;總共有 3 …