订阅发布模式的详解

一、订阅发布模式详解

订阅发布模式是一种设计模式,其基本思想是一个对象(被称为发布者)不需要直接把信息传递给另一个对象(被称为订阅者),而是通过一个叫做“消息中心”的中介来实现发布者与订阅者之间的松耦合。

订阅发布模式可以应用于许多场景,比如在 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/n/145465.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
IOGPIOGP
上一篇 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

发表回复

登录后才能评论