简单实现发布订阅模式

一.什么是发布订阅模式?

专业点讲,发布订阅就是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在,而订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者存在。

浅显的来说,发布订阅有三个点:发布者(发送消息的人),消息储存点(存放消息的地方),订阅者(想要接收消息的人)。发布者只需要创建消息来发布,订阅者可以选择喜欢的消息来接收,也可以选择取消订阅消息。

二.简单实现发布订阅

1.首先我需要一个消息软件

/* 我的消息流通软件 */
class MyChatApp {

}

2.添加消息点(发布点,接收点,取消点,储存点)

/* 我的消息流通软件 */
class MyChatApp {

    // 消息存放地
    constructor() {
        this.cache = {};
    }


    //发布消息(申请成为发布人 以及提供所要发送的消息内容)
    sentMsg(name, ...args) {

    }

    // 订阅消息(订阅所想订阅的消息人,以及拿到订阅的消息后想做什么)
    subMsg(name, cb) {

    }

    // 取消订阅(所想取消订阅的消息发布人,以及订阅消息)
    unSubMsg(name, cb) {

    }

}

3.处理相应的功能逻辑

 首先明白我们把所有的消息都存放在存放点cache中的,

 在订阅的时候我们肯定是需要在消息存放点中搜索我们所需要订阅的消息发布人,并且拿到我们所需要订阅的消息(同一消息人可以发布多条消息,所以这里我们用数组储存)

 // 订阅消息(订阅所想订阅的消息人,以及拿到订阅的消息后想做什么)
 subMsg(name, cb) {
        // 如果当前消息没有订阅过,就给当前消息创建一个订阅点
        if (!this.cache[name]) {
            this.cache[name] = []; 
        }
        this.cache[name].push(cb);
 }

取消订阅的话直接删除订阅点就好了

   // 取消订阅(所想取消订阅的消息发布人,以及发布人所发布的哪条订阅消息)
   unSubMsg(name, cb) {
        const sendUser = this.cache[name];
        const index = sendUser.indexOf(cb);
        if (index !== -1) {
            // 删除消息(取消订阅该条消息)
            sendUser.splice(index, 1);
        }
   }

最后是发布消息

    //发布消息(申请成为发布人 以及提供所要发送的消息内容)
    sentMsg(name, ...args) {
        // 逐个调用队列里的回调函数
        this.cache[name].forEach((callback) => {
            callback(...args);
        });

        console.log('发布人:', name);
        console.log('发布消息:', ...args);
    }Ï

最后的完成效果

/* 我的消息流通软件 */
class MyChatApp {
    // 消息存放地
    constructor() {
        this.cache = {};
    }

    //发布消息(申请成为发布人 以及提供所要发送的消息内容)
    sentMsg(name, ...args) {
        console.log('-------------------');
        console.log('发布人:', name);
        console.log('发布消息:', ...args);
        // 逐个调用队列里的回调函数
        this.cache[name].forEach((callback) => {
            callback(...args);
        });
    }

    // 订阅消息(订阅所想订阅的消息人,以及拿到订阅的消息后想做什么)
    subMsg(name, cb) {
        // 如果当前消息没有订阅过,就给当前消息创建一个订阅点
        if (!this.cache[name]) {
            this.cache[name] = [];
        }
        this.cache[name].push(cb);
    }

    // 取消订阅(所想取消订阅的消息发布人,以及发布人所发布的哪条订阅消息)
    unSubMsg(name, cb) {
        const sendUser = this.cache[name];
        const index = sendUser.indexOf(cb);
        if (index !== -1) {
            // 删除消息(取消订阅该条消息)
            sendUser.splice(index, 1);
        }
    }
}

测试一下

// 创建一个消息流通软件
let  myChatApp = new MyChatApp();


// 创建订阅者
let firstMsg = function (...args) {
    console.log(`订阅者(小明爸爸)-小明同学在干嘛:${args}`)
}

// 创建订阅者
let secondMsg = function (...args) {
    console.log(`订阅者(小明妈妈)-小明同学在干嘛:${args}`)
}


// 订阅消息(订阅班主任发布的消息)
myChatApp.subMsg("班主任", firstMsg);
myChatApp.subMsg("班主任", secondMsg);

// 发布消息(班主任发布消息)
myChatApp.sentMsg("班主任", "上体育课课", "打篮球", "受伤");
myChatApp.sentMsg("班主任", "上数学课", "写奥数", "得奖");

最后测试结果

以上就是实现一个简单的发布订阅啦

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用IPC实现发布订阅模式的C语言代码示例: 1. 发布者代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <rtthread.h> #define MQ_NAME "mq_magic_test" #define MQ_SIZE 1024 static rt_mq_t mq_magic_pub = RT_NULL; int pub_thread_entry(void *parameter) { char msg[MQ_SIZE]; int i = 0; while (1) { sprintf(msg, "This is message %d from publisher.", i++); rt_mq_send(mq_magic_pub, msg, strlen(msg)); rt_kprintf("Publish message: %s\n", msg); rt_thread_mdelay(1000); } } int pub_init(void) { mq_magic_pub = rt_mq_create(MQ_NAME, MQ_SIZE, RT_IPC_FLAG_FIFO); if (mq_magic_pub == RT_NULL) { rt_kprintf("Failed to create message queue.\n"); return -1; } rt_thread_t pub_tid = rt_thread_create("pub", pub_thread_entry, RT_NULL, 1024, 25, 10); if (pub_tid != RT_NULL) { rt_thread_startup(pub_tid); } return 0; } MSH_CMD_EXPORT(pub_init, ipc pub/sub demo); ``` 2. 订阅者代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <rtthread.h> #define MQ_NAME "mq_magic_test" #define MQ_SIZE 1024 static rt_mq_t mq_magic_sub = RT_NULL; int sub_thread_entry(void *parameter) { char msg[MQ_SIZE]; while (1) { rt_memset(msg, 0, sizeof(msg)); rt_mq_recv(mq_magic_sub, msg, sizeof(msg), RT_WAITING_FOREVER); rt_kprintf("Receive message: %s\n", msg); } } int sub_init(void) { mq_magic_sub = rt_mq_create(MQ_NAME, MQ_SIZE, RT_IPC_FLAG_FIFO); if (mq_magic_sub == RT_NULL) { rt_kprintf("Failed to create message queue.\n"); return -1; } rt_thread_t sub_tid = rt_thread_create("sub", sub_thread_entry, RT_NULL, 1024, 25, 10); if (sub_tid != RT_NULL) { rt_thread_startup(sub_tid); } return 0; } MSH_CMD_EXPORT(sub_init, ipc pub/sub demo); ``` 以上代码中,发布者通过创建一个消息队列mq_magic_pub,并在一个线程中不断发送消息;订阅者通过创建一个同名的消息队列mq_magic_sub,并在一个线程中不断接收消息。这样就实现了一个简单发布订阅模式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值