訂閱發佈模式的詳解

一、訂閱發佈模式詳解

訂閱發佈模式是一種設計模式,其基本思想是一個對象(被稱為發佈者)不需要直接把信息傳遞給另一個對象(被稱為訂閱者),而是通過一個叫做「消息中心」的中介來實現發佈者與訂閱者之間的松耦合。

訂閱發佈模式可以應用於許多場景,比如在 GUI 應用程序中實現事件驅動編程、在多線程應用程序中進行線程間通信、在松耦合的系統中實現消息傳遞機制等等。

二、觀察者模式和發佈訂閱模式的區別

訂閱發佈模式與觀察者模式很相似,但是它們有一些重要的區別。觀察者模式中,被觀察者和觀察者之間是直接聯繫的,觀察者會在被觀察者數據變化時被調用,而訂閱發佈模式中通過消息中心來傳遞消息,被稱為「松耦合」。

此外,觀察者模式通常只有一個觀察者,而訂閱發佈模式可以有多個訂閱者同時接收同一消息。

三、訂閱發佈模式有什麼優點

訂閱發佈模式有以下優點:

  • 松耦合:發佈者和訂閱者之間沒有直接的依賴關係,發佈者只需要知道消息中心,而訂閱者只需要關注自己感興趣的消息類型。
  • 擴展性強:通過新增消息類型可以輕鬆擴展訂閱發佈模式。
  • 可維護性強:由於發佈者和訂閱者之間不存在直接聯繫,因此代碼結構更加清晰,易於維護和修改。

四、訂閱發佈模式怎麼寫

在訂閱發佈模式中,一般需要實現三部分代碼:

  • 消息中心:負責維護消息列表和訂閱列表,還需要實現消息發佈和訂閱管理方法。
  • 發佈者:發佈者需要向消息中心註冊自己感興趣的消息類型,並在需要發佈消息時通過消息中心發佈。
  • 訂閱者:訂閱者需要從消息中心訂閱自己感興趣的消息類型,並實現對應的消息處理方法。

五、發佈訂閱模式使用場景

訂閱發佈模式可以在很多場景中使用:

  • 實現 GUI 應用程序中的事件驅動編程
  • 多線程應用程序中進行線程間通信
  • 松耦合的系統中實現消息傳遞機制

六、訂閱發佈模式細解

下面我們通過一個簡單的示例來演示如何實現訂閱發佈模式。

1. 消息中心


class MessageCenter {
  constructor() {
    this.messages = {};
    this.subscribers = {};
  }

  register(message, target) {
    if (!this.messages[message]) {
      this.messages[message] = [];
    }
    this.messages[message].push(target);
    if (!this.subscribers[target]) {
      this.subscribers[target] = [];
    }
    this.subscribers[target].push(message);
  }

  unregister(message, target) {
    if (!this.messages[message]) {
      return;
    }
    const index = this.messages[message].indexOf(target);
    if (index !== -1) {
      this.messages[message].splice(index, 1);
    }
    const subscriberIndex = this.subscribers[target].indexOf(message);
    if (subscriberIndex !== -1) {
      this.subscribers[target].splice(subscriberIndex, 1);
    }
  }

  publish(message, data) {
    if (!this.messages[message]) {
      return;
    }
    this.messages[message].forEach(target => {
      target.receiveMessage(message, data);
    });
  }

  getSubscriptions(target) {
    return this.subscribers[target] || [];
  }
}

消息中心包含了三個屬性:messages、subscribers 和 messagingCenter,用來維護消息列表、訂閱者列表以及消息中心實例。它還定義了四個方法:register()、unregister()、publish() 和 getSubscriptions()。

其中 register() 方法用來向消息中心註冊感興趣的消息類型,unregister() 方法用來取消註冊。publish() 方法用來發佈消息,getSubscriptions() 方法用來獲取訂閱者列表。

2. 發佈者


class Publisher {
  constructor(messageCenter) {
    this.messageCenter = messageCenter;
  }

  publish(message, data) {
    this.messageCenter.publish(message, data);
  }

  subscribe(message) {
    this.messageCenter.register(message, this);
  }

  unsubscribe(message) {
    this.messageCenter.unregister(message, this);
  }

  getSubscriptions() {
    return this.messageCenter.getSubscriptions(this);
  }
}

發佈者包含一個 messageCenter 屬性,用來發送消息。它還定義了三個方法:publish()、subscribe() 和 unsubscribe()。publish() 方法用來發佈消息,subscribe() 方法用來訂閱消息,unsubscribe() 方法用來取消訂閱。

3. 訂閱者


class Subscriber {
  constructor(name) {
    this.name = name;
  }

  receiveMessage(message, data) {
    console.log(`${this.name} received message "${message}" with data:`, data);
  }
}

訂閱者包含一個 name 屬性,用來標識它自己。它實現了 receiveMessage() 方法,用來處理接收到的消息。

4. 使用示例


// 創建一個消息中心實例
const messageCenter = new MessageCenter();

// 創建兩個訂閱者實例
const subscriber1 = new Subscriber("Subscriber 1");
const subscriber2 = new Subscriber("Subscriber 2");

// 創建一個發佈者實例,並向消息中心註冊一個 "event" 消息類型
const publisher = new Publisher(messageCenter);
publisher.subscribe("event");

// 訂閱者 1 訂閱 "event" 消息類型,並處理消息
subscriber1.getSubscriptions(); // []
subscriber1.receiveMessage = function (message, data) {
  console.log(`${this.name} received message "${message}" with data:`, data);
};
subscriber1.subscribe("event");

// 訂閱者 2 訂閱 "event" 消息類型,並處理消息
subscriber2.getSubscriptions(); // []
subscriber2.receiveMessage = function (message, data) {
  console.log(`${this.name} received message "${message}" with data:`, data);
};
subscriber2.subscribe("event");

// 發佈者發佈 "event" 消息類型,並攜帶數據
publisher.publish("event", { foo: "bar" });

// 控制台輸出:
// Subscriber 1 received message "event" with data: { foo: "bar" }
// Subscriber 2 received message "event" with data: { foo: "bar" }

以上代碼創建了一個消息中心實例 messageCenter,兩個訂閱者實例 subscriber1 和 subscriber2,以及一個發佈者實例 publisher。發佈者向消息中心註冊了 “event” 消息類型,兩個訂閱者訂閱了這個消息類型,並處理了接收到的消息。

七、訂閱發佈文件模式

訂閱發佈文件模式(也稱為 AMD 模式)是訂閱發佈模式的一種變體,它特別適合在 Web 應用程序中使用。下面的代碼示例演示了如何使用訂閱發佈文件模式(使用 RequireJS 庫實現):


// module1.js
define(["messageCenter"], function (messageCenter) {
  const module1 = {};

  module1.doSomething = function () {
    messageCenter.publish("event", { foo: "bar" });
  };

  return module1;
});

// module2.js
define(["messageCenter"], function (messageCenter) {
  const module2 = {};

  module2.showMessage = function (message, data) {
    console.log(`Message "${message}" received with data:`, data);
  };

  messageCenter.subscribe("event", module2.showMessage);

  return module2;
});

// messageCenter.js
define(function () {
  const messageCenter = {};

  const messages = {};

  messageCenter.publish = function (message, data) {
    if (!messages[message]) {
      return;
    }
    messages[message].forEach(function (callback) {
      callback(data);
    });
  };

  messageCenter.subscribe = function (message, callback) {
    if (!messages[message]) {
      messages[message] = [];
    }
    messages[message].push(callback);
  };

  return messageCenter;
});

// app.js
require(["module1", "module2"], function (module1, module2) {
  module1.doSomething();
});

以上代碼中,module1.js 依賴於 messageCenter.js 模塊,用來發佈消息;module2.js 也依賴於 messageCenter.js 模塊,用來訂閱消息。在 app.js 中,使用 RequireJS 庫來加載 module1.js 和 module2.js 模塊,並執行 module1.doSomething()。

八、訂閱發佈模式 JS 庫

訂閱發佈模式是一種常用的設計模式,因此市面上有許多成熟的 JS 庫可供使用。

以下是一些值得推薦的訂閱發佈模式相關的 JS 庫:

  • PubSubJS:一個輕量級、可靠的訂閱發佈庫。
  • EventEmitter2:高級事件模塊,具有同步和異步發佈,命名空間支持,按需加載的監聽器和錯誤處理等功能。
  • postal.js:另一個用於實現消息訂閱/發佈的優秀庫,支持 IE6+ 和現代瀏覽器。
  • Mediator.js:支持基於模塊的事件中心。

原創文章,作者:IOGP,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/145465.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
IOGP的頭像IOGP
上一篇 2024-10-27 23:49
下一篇 2024-10-27 23:49

相關推薦

  • 手機安全模式怎麼解除?

    安全模式是一種手機自身的保護模式,它會禁用第三方應用程序並使用僅限基本系統功能。但有時候,安全模式會使你無法使用手機上的一些重要功能。如果你想解除手機安全模式,可以嘗試以下方法: …

    編程 2025-04-28
  • Qt State Machine與狀態機模式

    本文將介紹Qt State Machine和狀態機模式在Qt中的實現。Qt提供了QStateMachine和QState兩個類,可以方便地實現狀態機模式,並且能有效地處理複雜的、多…

    編程 2025-04-27
  • 顯示C++設計模式

    本文將詳細介紹顯示C++設計模式的概念、類型、優點和代碼實現。 一、概念 C++設計模式是在軟件設計階段定義,用於處理常見問題的可重用解決方案。這些解決方案是經過測試和驗證的,並已…

    編程 2025-04-27
  • Centos7進入單用戶模式的解釋

    本文將介紹如何在Centos7中進入單用戶模式,並從以下幾個方面進行詳細的闡述。 一、Centos7進入單用戶模式的解答 在Centos7中進入單用戶模式需要執行以下步驟: 1. …

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分佈式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25

發表回復

登錄後才能評論