觀察者模式與發佈訂閱模式真的不一樣

這兩個模式很容易弄混,很容易讓人以爲這兩個模式是相同的。可是首先咱們要知道的是,這兩個模式是不一樣的。硬要說相同的話,那也是廣義上的相同(後面下文解釋)。咱們先來各自看看這兩種模式,最後再搞清楚這二者間的聯繫與區別。設計模式

觀察者模式

概念

是軟件設計模式的一種。在此種模式中,一個目標對象管理全部相依於它的觀察者對象,而且在它自己的狀態改變時主動發出通知。這一般透過呼叫各觀察者所提供的方法來實現。此種模式一般被用來實時事件處理系統。bash

簡單來講,觀察者模式就是,一個對象(被觀察者)的狀態發生改變時,會通知全部依賴它的對象(觀察者),這二者是直接關聯的。函數

如圖所示,當Subject(被觀察對象)狀態發生變化時,會給 全部的Observers(觀察者們)發送一個通知函數,觀察者們接收到通知後一般會調用各自的更新函數。

舉一個栗子

咱們去餐廳吃飯的時候,常常會遇到須要排隊的時候。咱們能夠把餐廳看做時被觀察者,把排隊的客人(拿號排隊)看做是觀察者。當餐廳有位置的時候,餐廳會出來通知排隊的客人,到100號桌吃飯啦。這時排隊的客人們都會看看本身手上的號,肯定是否到本身吃飯了。學習

實現

const Subject = (() => {
    const observers = [];
    const addOb = (ob) => {
        observers.push(ob);
    };
    const notify = () => {
        for (let ob of observers) {
            if (typeof ob.update === 'function') {
                ob.update();
            }
        }
    };
    return {addOb, notify};
})();

let subA = {
    update: () => {
        console.log('updateSubA');
    }
},
    subB = {
        update: () => {
            console.log('updateSubB');
        }
    };
Subject.addOb(subA);    //添加觀察者subA
Subject.addOb(subB);    //添加觀察者subB
Subject.notify();       //通知全部觀察者
複製代碼

訂閱發佈模式

概念

是一種消息範式,消息的發送者(稱爲發佈者)不會將消息直接發送給特定的接收者(稱爲訂閱者)。而是將發佈的消息分爲不一樣的類別,無需瞭解哪些訂閱者(若是有的話)可能存在。一樣的,訂閱者能夠表達對一個或多個類別的興趣,只接收感興趣的消息,無需瞭解哪些發佈者(若是有的話)存在。ui

發佈者狀態更新時,發佈某些類型的通知,只通知訂閱了相關類型的訂閱者。發佈者和訂閱者之間是沒有直接關聯的。spa

如上圖所示,發佈者與訂閱者直接不是互相依賴和關聯的,二者之間有一個通訊結構(事件通道)。這個事件通道會處理髮布者發佈的不一樣類型的通知,而且將這些通知發送給相應的訂閱者。

舉一個栗子

仍是以餐廳排隊吃飯爲例。此次咱們拿了號後,再也不傻傻地在餐廳門口等待。咱們掃了一下排隊二維碼,咱們在排隊的過程當中就能夠去幹其餘事情了,由於到咱們的號時,餐廳會發送一個通知給咱們。設計

實現

const PubSub = (() => {
    const topics = {};  //保存訂閱主題
    const subscribe = (type, fn) => {   //訂閱某類型主題
        if (!topics[type]) {
            topics[type] = [];
        }
        topics[type].push(fn);
    };
    const publish = (type, ...args) => {    //發佈某類型主題
        if (!topics[type]) {
            return;
        }
        for (let fn of topics[type]) {      //通知相關主題訂閱者
            fn(args);
        }
    };
    return {subscribe, publish};
})();

let subA = {type: 'event1'},
    subB = {type: 'event2'},
    subC = {type: 'event1'};
PubSub.subscribe(subA.type, () => console.log(`update eventType: ${subA.type} subA`));   //訂閱者A訂閱topic1
PubSub.subscribe(subB.type, () => console.log(`update eventType: ${subB.type} subB`));   //訂閱者B訂閱topic2
PubSub.subscribe(subC.type, () => console.log(`update eventType: ${subC.type} subC`));   //訂閱者C訂閱topic1
PubSub.publish(subA.type);  //發佈topic通知,通知訂閱者A、C
複製代碼

聯繫與區別

聯繫

廣義上來講,觀察者模式和發佈-訂閱模式,都是一個對象的狀態發生變化,通知相關聯的對象。因此廣義上來講,這兩種模式是類似的,正如《Head First設計模式》所說。code

發佈 + 訂閱 = 觀察者模式cdn

區別

先來看一張圖,左邊是觀察者模型,右邊是發佈-訂閱者模型。結合這個圖和上文的分析,咱們能夠總結下這二者的區別。

  • 觀察者模式中,被觀察者(可理解爲發佈者)與觀察者(可理解爲訂閱者),這二者之間是直接關聯互相依賴的。而發佈-訂閱模式中,發佈者與訂閱者是不直接關聯的,它們之間多了一個事件通道,經過這個事件通道把發佈者和訂閱者關聯起來。
  • 觀察者模式中,被觀察者發佈通知,全部觀察者都會收到通知。發佈-訂閱模式中,發佈者發佈通知,只有特定類型的訂閱者會收到通知。
  • 觀察者模式中,被觀察者發出狀態更新通知後,觀察者調用自身內部的更新方法。發佈-訂閱模式中,訂閱者的更新是經過事件通道進行細節處理和響應更新的。

圖片來源:MSDNserver

本文旨在互相學習,本文屬我的理解,有說的不對的地方,師請糾正。轉載請註明原帖。

相關文章
相關標籤/搜索