觀察者模式
定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都將獲得通知前端
發佈—訂閱模式又叫觀察者模式,它定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都將獲得通知。在 JavaScript 開發中,咱們通常用事件模型來替代傳統的發佈—訂閱模式。函數
舉個栗子:ui
賣水果的張老闆和王老闆都要進一批香蕉,他們的水果都是在一個叫錢多多(下面統稱爲錢老闆)的水果批發商那裏進的。當張老闆和王老闆到錢老闆那裏進水果的時候,錢老闆告訴張老闆和王老闆,香蕉尚未到貨,得過幾天才到貨。無奈之下,張老闆和王老闆都把他們的電話號碼留在了錢老闆那裏,囑咐錢老闆,香蕉到貨後,第一時間通知他們。this
上面錢老闆就扮演了發佈者的角色,張老闆和王老闆則扮演的是訂閱者角色。在香蕉到貨後,錢老闆會主動給張老闆和王老發消息,讓兩位老闆來取香蕉。這樣的好處就是:香蕉沒到的這段時間,張老闆和王老闆能夠作其餘的事情,不用主動聯繫錢老闆,只需等待錢老闆的消息便可。也就是程序代碼中的時間上解耦,對象間解耦。spa
其實觀察者模式咱們都曾使用過,就是咱們熟悉的事件
可是內置的事件不少時候不能知足咱們的要求
因此咱們須要自定義事件code
如今咱們想實現這樣的功能 定義一個事件對象,它有如下功能對象
固然咱們不可能只訂閱一個事件,可能會有不少
因此咱們要針對不一樣的事件設置不一樣的」鍵」
這樣咱們儲存事件的結構應該是這樣的接口
EventList = {
evtName1: [回調函數1,回調函數2,...],
evtName2: [回調函數1,回調函數2,...],
evtName3: [回調函數1,回調函數2,...],
}
複製代碼
代碼以下事件
var createEventSys = function(){
return {
// 經過on接口監聽事件eventName
// 若是事件eventName被觸發,則執行callback回調函數
on: function (eventName, callback) {
//若是Event對象沒有handles屬性,則給Event對象定義屬性handles,初始值爲{}
//handles屬性是用來存儲事件和回調執行函數的(即存儲訂閱的事件和觸發事件後執行的相應函數方法)
if(!this.handles){
this.handles={};
}
//若是handles中不存在事件eventName,則將事件存儲在handles中,同時初始化該事件對應的回調邏輯函數集合
if(!this.handles[eventName]){
this.handles[eventName]=[];
}
//往handles中的eventName對應的回調邏輯函數集合push回調函數callback
this.handles[eventName].push(callback);
},
// 觸發事件 eventName
emit: function (eventName) {
//若是事件eventName有訂閱者,則依次執行事件eventName的訂閱者相應的回調方法
if(this.handles[arguments[0]]){
for(var i=0;i<this.handles[arguments[0]].length;i++){
this.handles[arguments[0]][i](arguments[1]);
}
}
},
//移除事件 eventName
remove: function (eventName, fn) {
//判斷事件eventName是否存在fn這個觀察者,若是有,則移除事件eventName的fn觀察者
if(this.handles[eventName]){
for(var i=0; i<this.handles[eventName].length; i++){
if(this.handles[eventName][i] === fn){
this.handles[eventName].splice(i,1);
break;
}
}
}
}
};
}
var Event = createEventSys();
Event.on('test', function (result) {
console.log(result);
});
Event.on('test', function () {
console.log('test');
});
Event.emit('test', 'hello world'); // 輸出 'hello world' 和 'test'
//對象person1和對象person2拓展複用自定義系統
var person1 = {};
var person2 = {};
Object.assign(person1, createEventSys());
Object.assign(person2, createEventSys());
person1.on('call1', function () {
console.log('person1');
});
person2.on('call2', function () {
console.log('person2');
});
person1.emit('call1'); // 輸出 'person1'
person1.emit('call2'); // 沒有輸出
person2.emit('call1'); // 沒有輸出
person2.emit('call2'); // 輸出 'person2'
複製代碼
如上面代碼這樣,咱們用觀察者模式就實現了一個基本完善的自定義事件系統。ip
觀察者模式有兩個明顯的優勢
時間上解耦
對象間解耦
在前端開發中,不少地方都適合用觀察者模式來作,在適當的地方善用觀察者模式
但願這篇文章對你們有幫助,喜歡的話,請關注我,我會持續更新一些技術文章到個人掘金主頁,謝謝你們支持!