訂閱發佈只觸發需要發佈的事件,解耦保密性強。
觀察者模式則爲觀察者列表發現有觸發信號則同步觸發,再判斷自己是否執行,耦合度高,信息每個觀察者都能接收到
觀察者模式和發佈訂閱模式最大的區別就是發佈訂閱模式有個事件調度中心。
觀察者模式
// 觀察者
class Observer {
constructor() {
}
update(val) {
}
}
// 觀察者列表
class ObserverList {
constructor() {
this.observerList = []
}
add(observer) {
return this.observerList.push(observer);
}
remove(observer) {
this.observerList = this.observerList.filter(ob => ob !== observer);
}
count() {
return this.observerList.length;
}
get(index) {
return this.observerList(index);
}
}
// 目標
class Subject {
constructor() {
this.observers = new ObserverList();
}
addObserver(observer) {
this.observers.add(observer);
}
removeObserver(observer) {
this.observers.remove(observer);
}
notify(...args) {
let obCount = this.observers.count();
for (let index = 0; index < obCount; index++) {
this.observers.get(i).update(...args); // 每一個觀察者都會接受到更新消息
}
}
}
訂閱發佈模式
var salesOffices = {}; // 定義售樓處
// 事件調度中心
salesOffices.clientList = {}; // 緩存列表,存放訂閱者的回調函數
salesOffices.listen = function( key, fn ){
if ( !this.clientList[ key ] ){ // 如果還沒有訂閱過此類消息,給該類消息創建一個緩存列表
// // 事件調度中心
this.clientList[ key ] = [];
}
this.clientList[ key ].push( fn ); // 訂閱的消息添加進消息緩存列表
};
salesOffices.trigger = function(){ // 發佈消息
var key = Array.prototype.shift.call( arguments ), // 取出消息類型
fns = this.clientList[ key ]; // 取出該消息對應的回調函數集合
if ( !fns || fns.length === 0 ){ // 如果沒有訂閱該消息,則返回
return false;
}
for( var i = 0, fn; fn = fns[ i++ ]; ){
fn.apply( this, arguments ); // (2) // arguments 是發佈消息時附送的參數
}
};
salesOffices.listen( 'squareMeter88', function( price ){ // 小明訂閱88 平方米房子的消息
console.log( '價格= ' + price ); // 輸出: 2000000
});
salesOffices.listen( 'squareMeter110', function( price ){ // 小紅訂閱110 平方米房子的消息
console.log( '價格= ' + price ); // 輸出: 3000000
});
salesOffices.trigger( 'squareMeter88', 2000000 ); // 發佈88 平方米房子的價格
salesOffices.trigger( 'squareMeter110', 3000000 ); // 發佈110 平方米房子的價格