1. 程式人生 > >訂閱發布模式和觀察者模式真的不一樣

訂閱發布模式和觀察者模式真的不一樣

參考資料 csharp net 結構 com dash 通知操作 模式 發布-訂閱模式

1、觀察者模式

觀察者模式定義了對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都將得到通知,並自動更新。觀察者模式屬於行為型模式,行為型模式關註的是對象之間的通訊,觀察者模式就是觀察者和被觀察者之間的通訊。

觀察者模式有一個別名叫“發布-訂閱模式”,或者說是“訂閱-發布模式”,訂閱者和訂閱目標是聯系在一起的,當訂閱目標發生改變時,逐個通知訂閱者。我們可以用報紙期刊的訂閱來形象的說明,當你訂閱了一份報紙,每天都會有一份最新的報紙送到你手上,有多少人訂閱報紙,報社就會發多少份報紙,報社和訂報紙的客戶就是上面文章開頭所說的“一對多”的依賴關系。

2、訂閱-發布模式

其實24種基本的設計模式中並沒有發布訂閱模式,上面也說了,他只是觀察者模式的一個別稱。

但是經過時間的沈澱,似乎他已經強大了起來,已經獨立於觀察者模式,成為另外一種不同的設計模式。

在現在的發布訂閱模式中,稱為發布者的消息發送者不會將消息直接發送給訂閱者,這意味著發布者和訂閱者不知道彼此的存在。在發布者和訂閱者之間存在第三個組件,稱為調度中心或事件通道,它維持著發布者和訂閱者之間的聯系,過濾所有發布者傳入的消息並相應地分發它們給訂閱者。

舉一個例子,你在微博上關註了A,同時其他很多人也關註了A,那麽當A發布動態的時候,微博就會為你們推送這條動態。A就是發布者,你是訂閱者,微博就是調度中心,你和A是沒有直接的消息往來的,全是通過微博來協調的(你的關註,A的發布動態)。

3、兩種模式的區別

我們先來看下這兩個模式的實現結構:

技術分享圖片

可以看出,發布訂閱模式相比觀察者模式多了個事件通道,事件通道作為調度中心,管理事件的訂閱和發布工作,徹底隔絕了訂閱者和發布者的依賴關系。即訂閱者在訂閱事件的時候,只關註事件本身,而不關心誰會發布這個事件;發布者在發布事件的時候,只關註事件本身,而不關心誰訂閱了這個事件。

觀察者模式有兩個重要的角色,即目標和觀察者。在目標和觀察者之間是沒有事件通道的。一方面,觀察者要想訂閱目標事件,由於沒有事件通道,因此必須將自己添加到目標(Subject) 中進行管理;另一方面,目標在觸發事件的時候,也無法將通知操作(notify) 委托給事件通道,因此只能親自去通知所有的觀察者。

我們再來看一下這兩個模式的代碼實現:

訂閱-發布模式

class PubSub {
    constructor() {
        this.subscribers = [];
    }
    
    subscribe(topic, callback) {
        let callbacks = this.subscribers[topic];
        if (!callbacks) {
            this.subscribers[topic] = [callback];
        } else {
            callbacks.push(callback);
        }
    }
    
    publish(topic, ...args) {
        let callbacks = this.subscribers[topic] || [];
        callbacks.forEach(callback => callback(...args));
    }
}

// 創建事件調度中心,為訂閱者和發布者提供調度服務
let pubSub = new PubSub();
// A訂閱了SMS事件(A只關註SMS本身,而不關心誰發布這個事件)
pubSub.subscribe(‘SMS‘, console.log);
// B訂閱了SMS事件
pubSub.subscribe(‘SMS‘, console.log);
// C發布了SMS事件(C只關註SMS本身,不關心誰訂閱了這個事件)
pubSub.publish(‘SMS‘, ‘I published `SMS` event‘);

觀察者模式

class Subject {
    constructor() {
        this.observers = [];
    }

    add(observer) {
        this.observers.push(observer);
    }

    notify(...args) {
        this.observers.forEach(observer => observer.update(...args));
    }
}

class Observer {
    update(...args) {
        console.log(...args);
    }
}

// 創建觀察者ob1
let ob1 = new Observer();
// 創建觀察者ob2
let ob2 = new Observer();
// 創建目標sub
let sub = new Subject();
// 目標sub添加觀察者ob1 (目標和觀察者建立了依賴關系)
sub.add(ob1);
// 目標sub添加觀察者ob2
sub.add(ob2);
// 目標sub觸發SMS事件(目標主動通知觀察者)
sub.notify(‘I fired `SMS` event‘);

從代碼實現可以看出,發布-訂閱模式是面向調度中心編程的,而觀察者模式則是面向目標和觀察者編程的。前者用於解耦發布者和訂閱者,後者用於耦合目標和觀察者,不可同日而語也~

參考資料

[1] 發布訂閱模式與觀察者模式

[2] 重學JS(九)—— 觀察者模式和發布/訂閱模式真不一樣

訂閱發布模式和觀察者模式真的不一樣