一文帶你理解JavaScript 觀察者模式
觀察者模式(Observer Pattern)是一種行為型設計模式,它定義了一種一對多的依賴關系,讓多個觀察者對象同時監(jiān)聽某一個主題對象,當主題對象發(fā)生變化時,它的所有觀察者都會收到通知并進行相應的處理。
觀察者模式包含兩個角色:
- 主題(Subject):被觀察的對象,它維護了一個觀察者列表,可以添加、刪除觀察者,以及通知觀察者狀態(tài)的變化。
- 觀察者(Observer):觀察主題的對象,當主題狀態(tài)發(fā)生變化時,它會接收到通知并進行相應的處理。
為什么需要觀察者模式
觀察者模式的價值在于它可以將主題對象和觀察者對象解耦,使得它們可以獨立地進行擴展和修改,同時也可以降低代碼的耦合度,提高代碼的可維護性和可擴展性。
具體來說,觀察者模式有以下幾個價值:
- 易于擴展
觀察者模式可以在不修改主題對象和觀察者對象的情況下,增加新的觀察者對象或者新的主題對象,從而實現(xiàn)系統(tǒng)的擴展性。
- 解耦
觀察者模式將主題對象和觀察者對象解耦,使得它們可以獨立地進行擴展和修改,降低了它們之間的依賴關系,提高了系統(tǒng)的靈活性。
- 通信
觀察者模式通過事件通知的方式,實現(xiàn)了主題對象和觀察者對象之間的通信,使得它們可以相互交流和協(xié)作,從而實現(xiàn)系統(tǒng)的功能。
總之,觀察者模式可以幫助我們更好地組織代碼,降低代碼的耦合度,提高代碼的可維護性和可擴展性,應用廣泛,是一種非常有價值的設計模式。
代碼示例
下面是一個簡單的觀察者模式的代碼示例:
// 主題對象
class Subject {
constructor() {
this.observers = []; // 觀察者列表
}
// 添加觀察者
addObserver(observer) {
this.observers.push(observer);
}
// 刪除觀察者
removeObserver(observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
}
// 通知所有觀察者狀態(tài)的變化
notify() {
for (const observer of this.observers) {
observer.update(this);
}
}
// 更改狀態(tài),并通知所有觀察者
setState(state) {
this.state = state;
this.notify();
}
}
// 觀察者對象
class Observer {
// 接收主題對象,并將自己添加到主題的觀察者列表中
constructor(subject) {
subject.addObserver(this);
}
// 接收通知并進行相應的處理
update() {
console.log('Observer update:', this);
}
}
// 創(chuàng)建主題和觀察者對象
const subject = new Subject();
const observer1 = new Observer(subject);
const observer2 = new Observer(subject);
// 更改主題狀態(tài),并通知所有觀察者
subject.setState('new state');這段代碼中,我們首先定義了一個主題對象 Subject,它維護了一個觀察者列表 observers,并提供了添加、刪除觀察者的方法,以及通知所有觀察者狀態(tài)變化的方法 notify。在 setState 方法中,我們將狀態(tài)賦值給 state,并調(diào)用 notify 方法通知所有觀察者。
然后定義了一個觀察者對象 Observer,它在構造函數(shù)中接收主題對象 subject,并將自己添加到 subject 的觀察者列表中。在 update 方法中,我們打印出觀察者自身的信息。
最后創(chuàng)建了一個主題對象 subject,以及兩個觀察者對象 observer1 和 observer2。調(diào)用 setState 方法更改主題狀態(tài),并通知所有觀察者。
應用場景
觀察者模式的應用場景很多,以下是幾個常見的場景及對應的代碼示例:
DOM事件監(jiān)聽:
常見的如click事件、mouse事件、keyboard事件等,通過addEventListener()方法注冊事件,當事件觸發(fā)時,將自動調(diào)用回調(diào)函數(shù)。
// 注冊事件監(jiān)聽
document.addEventListener('click', function() {
console.log('click事件觸發(fā)了!');
});數(shù)據(jù)綁定
當數(shù)據(jù)模型發(fā)生變化時,觀測者模式可通知視圖更新,保證數(shù)據(jù)與視圖同步。
// 定義對象屬性
let data = { name: '小明', age: 20 };
// 通過Object.defineProperty()方法添加get/set方法
Object.defineProperty(data, 'name', {
get: function() {
return this._name;
},
set: function(newName) {
console.log(`修改name屬性為:${newName}`);
this._name = newName;
}
});
// 修改對象屬性
data.name = '小紅';自定義事件
可通過自定義事件的方式實現(xiàn)觀察者模式,當自定義事件觸發(fā)時,所有訂閱者都會得到通知并執(zhí)行其回調(diào)函數(shù)。
// 創(chuàng)建自定義事件對象
const event = new Event('myCustomEvent');
// 注冊事件監(jiān)聽
document.addEventListener('myCustomEvent', function(event) {
console.log('自定義事件觸發(fā)了!');
});
// 觸發(fā)自定義事件
document.dispatchEvent(event);Promise對象
Promise對象可作為一種觀察者模式實現(xiàn)異步編程,當Promise對象狀態(tài)發(fā)生改變時,所有訂閱者都會得到通知并執(zhí)行其回調(diào)函數(shù)。
// 創(chuàng)建promise對象
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise執(zhí)行成功!');
}, 1000);
});
// 注冊promise狀態(tài)變化的回調(diào)函數(shù)
promise.then(function(data) {
console.log(data);
});Pub/Sub模式
Pub/Sub模式是一種松耦合的通信機制,可通過觀察者模式實現(xiàn)。當發(fā)布者發(fā)布消息時,所有訂閱者都會得到通知并執(zhí)行其回調(diào)函數(shù)。
// 創(chuàng)建Pub/Sub對象
const pubsub = {
subscribers: {},
subscribe(eventName, handler) {
// 添加事件訂閱者
if (!this.subscribers[eventName]) {
this.subscribers[eventName] = [];
}
this.subscribers[eventName].push(handler);
},
unsubscribe(eventName, handler) {
// 取消事件訂閱者
if (!this.subscribers[eventName]) {
return;
}
const index = this.subscribers[eventName].indexOf(handler);
this.subscribers[eventName].splice(index, 1);
},
publish(eventName, data) {
// 發(fā)布事件
if (!this.subscribers[eventName]) {
return;
}
this.subscribers[eventName].forEach((handler) => {
handler(data);
});
},
};
// 訂閱事件
pubsub.subscribe('myEvent', function(data) {
console.log(`收到myEvent事件,數(shù)據(jù)為:${data}`);
});
// 發(fā)布事件
pubsub.publish('myEvent', 'Hello World!');以上就是一文帶你理解JavaScript 觀察者模式的詳細內(nèi)容,更多關于JavaScript 觀察者模式的資料請關注腳本之家其它相關文章!
相關文章
一文帶你掌握JavaScript中Moment.js如何操作日期和時間
Moment.js是一個極其強大的JavaScript庫,專門用于解析、驗證、操作和顯示日期和時間,下面就跟隨小編一起學習一下Moment.js的具體使用吧2024-01-01
javascript 構造函數(shù)強制調(diào)用經(jīng)驗總結
本文將介紹javascript構造函數(shù)調(diào)用方面的案例應用,需要了解的朋友可以參考下2012-12-12
layui在form表單頁面通過Validform加入簡單驗證的方法
今天小編就為大家分享一篇layui在form表單頁面通過Validform加入簡單驗證的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09
JavaScript利用canvas實現(xiàn)炫酷的碎片切圖效果
這篇文章主要和大家分享一個炫酷的碎片式切圖效果,本文主要利用canvas來實現(xiàn),代碼量不多,但有些地方還是需要花點時間去理解的,感興趣的可以學習一下2022-10-10
微信小程序webview中監(jiān)聽返回按鈕實現(xiàn)步驟
在微信小程序中webview返回鍵是一個非常實用的功能,它允許用戶在嵌入的網(wǎng)頁中返回到上一個頁面,這篇文章主要給大家介紹了微信小程序webview中監(jiān)聽返回按鈕的實現(xiàn)步驟,需要的朋友可以參考下2024-08-08
JavaScript高級程序設計閱讀筆記(五) ECMAScript中的運算符(一)
ECMAScript中的運算符,學習js的朋友可以看看2012-02-02
JS實現(xiàn)消息來時讓網(wǎng)頁標題閃動效果的方法
這篇文章主要介紹了JS實現(xiàn)消息來時讓網(wǎng)頁標題閃動效果的方法,實例分析了JavaScript基于時間函數(shù)動態(tài)操作頁面元素的技巧,并附帶了開心網(wǎng)的標題閃動解決方案,需要的朋友可以參考下2016-04-04

