設計模式 行為型 觀察者模式(Observer Pattern)與 常見技術框架應用 解析

在這里插入圖片描述

觀察者模式(Observer Pattern)是一種行為設計模式,它定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新。

一、核心思想

觀察者模式的核心思想是解耦主題(被觀察者)和觀察者,使得它們可以獨立變化而不會相互影響。這有助于降低對象之間的耦合度,提高系統的可擴展性和可維護性。

二、定義與結構

1. 定義

觀察者模式定義了對象之間的一種一對多依賴關系,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知并被自動更新。

2. 結構

  • Subject(主題):也稱為被觀察者,它是一個接口或者抽象類,定義了添加、刪除和通知觀察者的方法。它維護了一個觀察者列表,當自身狀態發生變化時,通過遍歷這個列表來通知所有的觀察者。
  • ConcreteSubject(具體主題):實現了Subject接口,它包含了一些可以被觀察的狀態屬性,并且在這些狀態發生變化時,負責調用通知方法來通知觀察者。
  • Observer(觀察者):也是一個接口或者抽象類,它定義了一個更新方法,用于在收到主題通知時更新自己的狀態。
  • ConcreteObserver(具體觀察者):實現了Observer接口,它包含了用于存儲自身狀態的屬性,并且實現了更新方法,在更新方法中根據主題傳遞過來的信息更新自己的狀態。

三、角色

1. 主題(Subject)

  • 職責是管理觀察者對象的引用列表,提供添加和刪除觀察者的方法。
  • 當自身狀態發生變化時,負責通知所有已注冊的觀察者。

2. 觀察者(Observer)

  • 定義了一個更新接口,當收到主題的通知時,會調用這個更新接口來更新自己的狀態。

四、實現步驟及代碼示例

1. 定義觀察者接口

// 觀察者接口
public interface Observer {void update(String news);
}

2. 定義主題接口

import java.util.ArrayList;
import java.util.List;// 主題接口
public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers(String news);
}

3. 實現具體主題類

import java.util.ArrayList;
import java.util.List;// 具體主題類
public class NewsPublisher implements Subject {private List<Observer> observers = new ArrayList<>();private String latestNews;@Overridepublic void attach(Observer observer) {observers.add(observer);}@Overridepublic void detach(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(String news) {this.latestNews = news;for (Observer observer : observers) {observer.update(latestNews);}}
}

4. 實現具體觀察者類

// 具體觀察者類
public class NewsSubscriber implements Observer {private String name;public NewsSubscriber(String name) {this.name = name;}@Overridepublic void update(String news) {System.out.println(name + " received news: " + news);}
}

5. 測試代碼

public class Main {public static void main(String[] args) {NewsPublisher publisher = new NewsPublisher();NewsSubscriber subscriber1 = new NewsSubscriber("Subscriber 1");NewsSubscriber subscriber2 = new NewsSubscriber("Subscriber 2");publisher.attach(subscriber1);publisher.attach(subscriber2);publisher.notifyObservers("New technology released!");}
}

五、常見技術框架應用

1、Vue 2 數據劫持

在Vue 2中,觀察者模式是通過Object.defineProperty()方法實現的,這允許Vue能夠追蹤數據對象屬性的變化,并在變化發生時觸發相應的更新。以下是對Vue 2中基于Object.defineProperty()實現的觀察者模式的詳細解析:

1.1. 數據劫持

Vue 2 使用Object.defineProperty()來對數據對象的屬性進行劫持。這個方法允許我們定義一個對象屬性的getter和setter函數,當屬性被訪問或修改時,這些函數會被調用。

Object.defineProperty(obj, 'property', {get: function() {// 當屬性被訪問時執行的代碼},set: function(newValue) {// 當屬性被修改時執行的代碼}
});

在Vue中,當數據對象被創建時,Vue會使用Object.defineProperty()遍歷對象的所有屬性,并為它們設置getter和setter。這樣,當這些屬性在將來被訪問或修改時,Vue就能夠感知到。

1.2. 依賴收集

在getter函數中,Vue會進行依賴收集。所謂依賴收集,就是當某個屬性被訪問時,Vue會記錄下當前正在執行的Watcher(觀察者)。Watcher是Vue內部用于追蹤數據變化的機制,它會在數據變化時觸發相應的更新。

當組件渲染或計算屬性被計算時,它們會訪問數據對象的屬性,這時getter函數就會被調用,Vue就會記錄下當前的Watcher。

1.3. 派發更新

在setter函數中,當數據屬性被修改時,Vue會觸發setter函數。在這個函數中,Vue會遍歷之前收集的依賴(Watcher),并通知它們數據已經發生了變化,需要重新執行以更新視圖或計算屬性。

1.4. 觀察者(Watcher)

Watcher是Vue內部的一個類,它用于追蹤數據的變化并在數據變化時執行相應的回調函數。在Vue中,Watcher有三種類型:

  • 渲染Watcher:與組件的渲染函數相關聯,當數據變化時,它會重新渲染組件。
  • 計算屬性Watcher:與計算屬性相關聯,當計算屬性的依賴數據變化時,它會重新計算計算屬性的值。
  • 偵聽器Watcher:通過vm.$watch方法創建的Watcher,用于在數據變化時執行特定的回調函數。

1.5. 實現細節

Vue 2的內部實現非常復雜,但基于上述原理,我們可以簡化地理解其觀察者模式的實現過程:

  1. 初始化數據:使用Object.defineProperty()為數據對象的每個屬性設置getter和setter。
  2. 依賴收集:在getter函數中,檢查當前是否存在活動的Watcher(通常是在組件渲染或計算屬性計算時),如果存在,則將其添加到該屬性的依賴列表中。
  3. 派發更新:在setter函數中,當屬性值發生變化時,遍歷該屬性的依賴列表,并通知每個依賴(Watcher)數據已經變化,需要執行更新操作。

1.6. 注意事項

  • 由于Object.defineProperty()只能對對象的已有屬性進行劫持,因此Vue無法檢測到對象屬性的添加或刪除。為了解決這個問題,Vue提供了Vue.set()Vue.delete()方法。
  • 深度監聽:默認情況下,Vue只監聽對象的第一層屬性的變化。如果需要監聽嵌套對象的變化,可以在創建Vue實例時通過observe選項開啟深度監聽(但請注意性能開銷)。然而,在Vue 2中,深度監聽通常是通過遞歸地為嵌套對象設置getter和setter來實現的,而不是簡單地通過observe選項。實際上,observe選項在Vue 2中并不直接控制深度監聽。
  • 響應式系統的局限性:由于JavaScript的限制和性能考慮,Vue的響應式系統有一些局限性。例如,它不能檢測數組元素通過索引的直接修改或對象屬性的添加/刪除(除非使用Vue.set()/Vue.delete())。

綜上所述,Vue 2通過Object.defineProperty()實現了觀察者模式,使得Vue能夠追蹤數據對象屬性的變化并在變化發生時自動更新視圖。然而,由于JavaScript的限制和性能考慮,Vue的響應式系統有一些局限性需要注意。

2. JavaScript 中 事件監聽

// 創建一個按鈕元素
const button = document.createElement('button');
button.textContent = 'Click me';// 定義觀察者函數(事件處理函數)
const observerFunction = function () {console.log('Button was clicked!');
};// 主題(按鈕)添加觀察者(事件監聽)
button.addEventListener('click', observerFunction);// 將按鈕添加到文檔中
document.body.appendChild(button);

在這個JavaScript示例中,button是主題,observerFunction是觀察者。當按鈕被點擊(主題狀態改變)時,會觸發觀察者函數,這類似于觀察者模式的通知機制。

六、應用場景

當一個對象的改變需要同時改變其他對象,而不知道具體有多少個對象有待改變時。
當一個抽象模型有兩個方面,其中一個方面依賴于另一方面,這時可以通過觀察者模式將這兩者封裝在獨立的對象中以使它們各自獨立地改變和復用。
當對一個對象的改變需要廣播到其他對象時。

觀察者模式廣泛應用于各種需要通知多個對象進行同步更新的場合,包括但不限于:

  1. GUI事件監聽機制:在圖形用戶界面編程中,按鈕、文本框等控件的事件處理通常使用觀察者模式。
  2. 數據模型與視圖同步:在MVC架構中,觀察者模式常用于數據模型和視圖之間的更新同步。
  3. 發布-訂閱系統:觀察者模式是發布-訂閱系統的基礎,允許不同的服務訂閱某個主題并接收通知。
  4. 股票價格監控:在金融系統中,觀察者模式可以讓股票價格的變化自動通知所有依賴該數據的系統。
  5. 社交媒體的通知機制:當用戶發布新動態時,所有關注者都會收到通知。

七、優缺點

優點

  1. 解耦性高:主題和觀察者之間是松耦合的關系。主題只需要知道觀察者實現了更新方法,而不需要了解觀察者的具體細節。這樣可以方便地添加、刪除和替換觀察者,同時也使得主題和觀察者可以獨立地進行修改和擴展。
  2. 支持廣播通信:主題可以同時通知多個觀察者,使得系統能夠方便地實現一對多的消息傳遞機制,提高了信息傳播的效率。

缺點

  1. 可能導致性能問題:如果觀察者數量過多,當主題狀態發生變化時,通知所有觀察者可能會消耗較多的時間和資源。特別是在一些對性能要求較高的場景下,可能需要對通知機制進行優化,比如采用異步通知等方式。
  2. 存在循環依賴風險:如果觀察者在更新自己狀態的過程中又對主題進行了操作,可能會導致循環依賴,使得系統的邏輯變得復雜,甚至出現死循環等問題。在設計和實現過程中需要特別注意避免這種情況。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/65711.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/65711.shtml
英文地址,請注明出處:http://en.pswp.cn/web/65711.shtml

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

相關文章

03_Redis基本操作

1.Redis查詢命令 1.1 官網命查詢命令 為了便于學習Redis,官方將其用于操作不同數據類型的命令進行了分類整理。你可以通過訪問Redis官方網站上的命令參考頁面https://redis.io/commands來查閱這些分組的命令,這有助于更系統地理解和使用Redis的各項功能。 1.2 HELP查詢命令…

system securiry: supervisor password required

報錯解釋&#xff1a; 這個錯誤表明系統安全模塊&#xff08;如SELinux或AppArmor&#xff09;需要超級用戶&#xff08;通常是root&#xff09;的密碼來確認一個操作。這通常發生在嘗試進行某些需要高級權限的系統更改時。 解決方法&#xff1a; 如果你擁有root權限&#xff0…

Ubuntu 如何查看盤是機械盤還是固態盤

在 Ubuntu 系統中&#xff0c;您可以通過以下方法來確定硬盤是機械硬盤&#xff08;HDD&#xff09;還是固態硬盤&#xff08;SSD&#xff09;&#xff1a; 使用 lsblk 命令&#xff1a; 打開終端&#xff0c;輸入以下命令&#xff1a; lsblk -d -o name,rota該命令將列出所…

探索式測試

探索式測試是一種軟件測試風格&#xff0c;它強調獨立測試人員的個人自由和職責&#xff0c;為了持續優化其工作的價值&#xff0c;將測試學習、測試設計、測試執行和測試結果分析作為相互支持的活動&#xff0c;在整個項目實現過程中并行地執行。 選擇合適的探索式測試方法我…

uniapp 微信小程序內嵌h5實時通信

描述&#xff1a; 小程序webview內嵌的h5需要向小程序實時發送消息&#xff0c;有人說postMessage可以實現&#xff0c;所以試驗一下&#xff0c;結果是實現不了實時&#xff0c;只能在特定時機后退、組件銷毀、分享時小程序才能接收到信息&#xff08;小程序為了安全等考慮做了…

php 使用simplexml_load_string轉換xml數據格式失敗

本文介紹如何使用php函數解析xml數據為數組。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

HOW - Form 表單 label 和 wrapper 對齊場景

一、背景 在日常使用 表單 時&#xff0c;我們一般有如下布局&#xff1a; 可以通過 Form 表單提供的配置直接設置&#xff1a; <Formform{form}labelCol{{ span: 4 }}wrapperCol{{ span: 20 }}onFinish{handleSubmit}><Form.Itemlabel"輸入框"name"…

深入探索AI核心模型:CNN、RNN、GAN與Transformer

在人工智能的飛速發展中&#xff0c;眾多深度學習模型和算法不斷涌現&#xff0c;推動了許多領域的進步。特別是在圖像識別、自然語言處理、生成建模等方向&#xff0c;AI模型的應用越來越廣泛。本文將介紹幾種最常用的AI模型&#xff0c;包括卷積神經網絡&#xff08;CNN&…

櫻桃鍵盤win鍵按了沒反應怎么處理

?游戲模式?&#xff1a;部分櫻桃鍵盤在進入游戲模式后會禁用Win鍵&#xff0c;以防止在游戲過程中誤觸。可以通過按下Fn F9鍵來切換游戲模式和辦公模式&#xff0c;確保鍵盤處于辦公模式下&#xff0c;Win鍵即可恢復正常功能。? &#xff08;至此我的問題已解決&#xff0c…

解析若依 `R.java` 類——ruoyi-common-core

文章目錄 1. 類的整體功能2. 代碼解析2.1 成員變量和常量2.2 靜態方法構造響應對象2.3 內部私有方法 restResult2.4 工具方法 3. 開發中的應用擴展3.1 接口規范化3.2 快速響應構造3.3 自定義狀態碼3.4 自定義擴展 R.java 是若依框架中通用的 API 響應封裝類&#xff0c;主要用于…

Perl語言的數據結構

Perl語言的數據結構 Perl是一種功能強大的、靈活的腳本語言&#xff0c;廣泛用于文本處理、系統管理、網絡編程以及許多其他領域。其靈活性不僅體現在語法上&#xff0c;還體現在其豐富的數據結構上。本文將深入探討Perl的主要數據結構&#xff0c;包括標量、數組、哈希以及引…

RK3588上CPU和GPU算力以及opencv resize的性能對比測試

RK3588上CPU和GPU算力以及opencv resize的性能對比測試 一.背景二.小結三.相關鏈接四.操作步驟1.環境搭建A.安裝依賴B.設置GPU為高性能模式C.獲取GPU信息D.獲取CPU信息 2.調用OpenCL SDK獲取GPU信息3.使用OpenCL API計算矩陣乘4.使用clpeak測試GPU的性能5.使用OpenBLAS測試CPU的…

轉運機器人在物流倉儲行業的優勢特點

在智能制造與智慧物流的浪潮中&#xff0c;一款革命性的產品正悄然改變著行業的面貌——富唯智能轉運機器人&#xff0c;它以卓越的智能科技與創新的設計理念&#xff0c;引領著物流領域步入一個全新的高效、智能、無人的時代。 一、解放雙手&#xff0c;重塑物流生態 富唯智能…

基于單片機的無線智能窗簾控制器的設計

摘 要 : 本文以單片機為控制核心 , 基于 PT2262/ 2272 無線收發模塊 , 實現了窗簾的無線遠程智能控制 . 該控制器通過高頻無線收發模塊實現了遙控窗簾的開合控制; 根據外部光線強弱實現自動開關窗簾 ; 根據設定時間自動完成開關過程; 通過語音播報當前環境溫濕度信息以…

linux centos掛載未分配的磁盤空間

使用到的命令 lshw -class disk -short hostnamectl fdisk /dev/sdb partprobe /dev/sdb mount /dev/sdb2 /opt/fastdfs/ mkfs.ext4 /dev/sdb2 mount -t ext4 /dev/sdb2 /opt/fastdfs/

Vivado中Tri_mode_ethernet_mac的時序約束、分析、調整——(一)時序約束的基本概念

1、基本概念 推薦閱讀&#xff0c;Ally Zhou編寫的《Vivado使用誤區與進階》系列文章&#xff0c;熟悉基本概念、tcl語句的使用。 《Vivado使用誤區與進階》電子書開放下載&#xff01;&#xff01; 2、Vivado中的語法例程 1&#xff09;語法例程 約束的語句可以參考vivado…

基于Spring Boot的城市垃圾分類管理系統設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…

springboot整合admin

1. 添加依賴 首先&#xff0c;在你的admin服務端pom.xml文件中添加Spring Boot Admin的依賴&#xff1a; <dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.5.4<…

【YOLOv8雜草作物目標檢測】

YOLOv8雜草目標檢測 算法介紹模型和數據集下載 算法介紹 YOLOv8在禾本科雜草目標檢測方面有顯著的應用和效果。以下是一些關鍵信息的總結&#xff1a; 農作物幼苗與雜草檢測系統&#xff1a;基于YOLOv8深度學習框架&#xff0c;通過2822張圖片訓練了一個目標檢測模型&#xff…

比亞迪夏直插家用MPV腹地,“迪王”開啟全面銷冠新征程

文/王俁祺 導語&#xff1a;比亞迪前腳剛收獲2024年的全面成功&#xff0c;后腳立刻就開始布局2025年的產品矩陣了。比亞迪夏的橫空出世&#xff0c;看來家用MPV市場也要感受“迪王”的恐怖如斯了。 家用MPV市場的“意外之喜” 1月8日&#xff0c;比亞迪夏終于在萬眾矚目之下…