Javascript设计模式-07-观察者模式(发布订阅模式)

2023-10-26

Javascript设计模式 - 07 - 观察者模式(发布订阅模式)

简介

观察者模式又叫发布订阅模式,他定义了一种一对多的关系,让多个观察者对象同时监听某一个主体对象,这个主体对象发生改变时就会通知所有观察者,使得他们能够自动更新自己

提供一种抽象的策略,以便订阅者能供彼此独立的应对改变

优点

  1. 可以被广泛的应用到异步编程中,是一种代替传统回调函数的方案

  2. 可以取代对象之间硬编码的通知机制,一个对象不再显示的调用另外一个对象的某个接口,发布订阅模式让两个对象松耦合的联系在一起,虽然不太清楚彼此的细节,但这不影响他们之间相互通信。有新的订阅者出现时,发布者的代码不需要任何的修改,同样发布者的需求改变时,也不会影响到之前的订阅者,只要约定的事件没有变化,就可以自由的改变他们

实现步骤

  1. 指定发布者
  2. 给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者
  3. 最后发布消息的时候,发布者会遍历这个缓存列表,依次触发里边的回调函数

一般的发布订阅

    // 定义发布平台
    function Platform () {
        // channel 用于存放不同频道的缓存列表
        this.channel = {};
        this.subId = 0;
    }

    // 
    Platform.prototype.subscribe = function (type, callback) {
        // 订阅
        if (!this.channel[type]) {
            // 没有这个类型就创建一个类型
            this.channel[type] = [];
        } 

        // 每个类型都是一个数组,存放订阅的回调和一个标识
        this.channel[type].push({
            func: callback,
            subId: this.subId 
        })

        return this.subId++;
    }

    Platform.prototype.emit = function (type, content) {
        // 发布消息
        if (!this.channel[type]) {
            return false;
        }
        this.channel[type].forEach(function (item) {
            !!item.func && item.func(type, content);
        })

    }

    Platform.prototype.unsubscribe = function (subId) {
        console.log(subId);
        var me = this;
        for (var type in me.channel) {
           if (me.channel.hasOwnProperty(type)) {
                // statement
                me.channel[type].forEach(function (item, i) {
                    Number(item.subId) === Number(subId) && me.channel[type].splice(i, 1);
                })  
           }
        }
    }


    // 实例化
    var plat = new Platform();
    var subId1 = plat.subscribe('/dev/home', function (type, content) {
        console.log(`subId1 type: ${type} content: ${content}`);
    })

    var subId2 = plat.subscribe('/dev/device', function (type, content) {
        console.log(`subId2 type: ${type} content: ${content}`);
    })

    var subId3 = plat.subscribe('/dev/home', function (type, content) {
        console.log(`subId3 type: ${type} content: ${content}`);
    })

    plat.emit('/dev/home', '/dev/home is emit!');
    // plat get type: /dev/home content: /dev/home is emit!
    // plat get type: /dev/home content: /dev/home is emit!

    plat.emit('/dev/device', '/dev/device is emit!');
    // subId2 type: /dev/device content: /dev/device is emit!

    // 取消订阅
    plat.unsubscribe(subId1);

    // 再次发布消息
    plat.emit('/dev/home', '/dev/home is emit again!');
    // subId3 type: /dev/home content: /dev/home is emit again!

全局的发布订阅

在一般的发布订阅模式中,发布者与订阅者之间还是存在一些耦合性的,如果有多个发布者,订阅者可能需要在多个发布者中注册订阅类似的事件,这样来看是一种资源的浪费,如果我们在发布者与订阅者之间增加一层中介,订阅者把请求交给中介,多个发布者都通过中介来发布信息,这样一来,订阅者不用关心消息是从哪个发布者订阅的,他只要在意是否接收到消息就可以了,为了保证订阅者、发布者都可以顺利通信,发布订阅模式可以使用一个全局对象作为中介,把订阅者和发布者联系起来。

先发布后订阅的离线消息

一般来讲我们都是先订阅一条消息,然后发布者发布,但是在某些情况下我们会遇到一个消息已经发布了,但是订阅者还没有出现,我们需要将这条消息保存下来,等到有对象订阅时,重新发布给订阅者,就像QQ离线消息一样。

操作步骤
  • 新建立一个存放离线事件的堆栈
  • 事件发布时如果还没有订阅者,就把发布事件的动作包裹在一个函数里,然后存到堆栈中
  • 等到有对象订阅此事件时,遍历堆栈,依次执行包装函数,重新发布事件

文章列表

  1. javascript设计模式 – 设计原则
  2. JavaScript设计模式–高阶函数
  3. Javascript 设计模式 - 01 - 原型模式
  4. Javascript 设计模式 - 02 - 单例模式
  5. Javascript 设计模式 - 03 - 建造者模式
  6. Javascript 设计模式 - 04 - 工厂模式
  7. Javascript 设计模式 - 05 - 外观模式
  8. Javascript 设计模式 - 06 - 代理模式
  9. Javascript 设计模式 - 07 - 观察者模式(发布订阅模式)
  10. Javascript 设计模式 - 08 - 策略模式
  11. Javascript 设计模式 - 09 - 命令模式
  12. Javascript 设计模式 - 10 - 迭代器模式
  13. Javascript 设计模式 - 11 - 职责链模式
  14. Javascript 设计模式 - 12 - 适配器模式
  15. Javascript 设计模式 - 13 - 模板方法
  16. Javascript 设计模式 - 14 - 组合模式
  17. Javascript 设计模式 - 15 - 享元模式
  18. Javascript 设计模式 - 16 - 中介者模式
  19. Javascript 设计模式 - 17 - 装饰者模式
  20. Javascript 设计模式 - 18 - 状态模式
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascript设计模式-07-观察者模式(发布订阅模式) 的相关文章

  • JavaScript 中的埃拉托斯特尼筛法对大量数据无限运行

    我一直在尝试写埃拉托斯特尼筛法 http en wikipedia org wiki Sieve of EratosthenesJavaScript 中的算法 基本上我只是按照以下步骤操作 创建从 2 到 n 1 的连续整数列表 令第一个素
  • 如何修改每个JSON对象javascript

    我想修改里面的每个 JSON 值cooldown object cooldown user 1 This user2 0 This 在 Javascript 中使用 for 语句 我研究了好几个小时 只找到了内部的 blocks Edit
  • 在新的 Google 协作平台 <嵌入 HTML> 中使用 localStorage 和 IndexedDB 不起作用

    我正在尝试将新的 Google 协作平台用于我开发的网页 但是 我在存储本地数据时遇到了问题 本地文件在 Windows 和 Apple safari chrome 中运行良好 从 Google 协作平台尝试一下 没有什么乐趣 此外 在 s
  • Chrome 中的性能问题

    我目前正在从事一个相对较大的项目 使用 AngularJs 构建 应用程序的一部分是一个表单 您可以向其中添加任意数量的页面 不幸的是 添加了很多不必要的垃圾 即表示表单模型的对象可能会变得非常大 在某些时候 Chrome 基本上无法处理它
  • 如何更改 Google Maps v3 API for Directions 中的开始和结束标记图像

    我使用 DirectionsRender 绘制了一条路线 但我不知道如何用我自己的标记替换通用的 Google 标记 我知道并在正常的谷歌地图情况下使用它 但发现很难用开始和结束的方向标记来做到这一点 如果这是一个愚蠢的问题 感谢您的任何建
  • 可以在初始 DOM 解析期间/之前修改 DOM 吗?

    是否可以在初始 DOM 解析期间或之前修改 DOM 或者我是否必须等到 DOM 被解析和构建之后才能与其交互 更具体地说 是否有可能阻止 DOM 中的脚本元素使用用户脚本 内容脚本或 Chrome 或 Firefox 中的类似脚本运行 在解
  • 在打字稿中导入 json

    我是 typescript 的新手 在我的项目中 我们使用 typescript2 在我的要求之一中 我需要导入 json 文件 所以我创建了 d ts 文件如下 test d ts declare module json const va
  • 如何纠正流警告:解构(缺少注释)

    我正在编写一个小型 React Native 应用程序 并且正在尝试使用 Flow 但我无法在任何地方真正获得有关它的正确教程 我不断收到错误 destructuring Missing annotation 有关 station 这段代码
  • 设置 cookie 时中断 JavaScript 执行

    当设置 cookie 时 是否可以始终中断浏览器开发人员工具中的 javascript 执行 无需显式设置 JS 断点 document cookie 在 html head 块的开头添加此代码片段效果很好
  • Javascript split 不是一个函数

    嘿朋友们 我正在使用 javascript sdk 通过 jQuery facebook 多朋友选择器在用户朋友墙上发布信息 但是我收到此错误friendId split 不是函数 这是我的代码 function recommendToFr
  • DataTables row.add 到特定索引

    我正在替换这样的行项目 var targetRow entity row dataTable targetRow closest table dataTable DataTable dataTable row targetRow remov
  • Firebase 函数 onWrite 未被调用

    我正在尝试使用 Firebase 函数实现一个触发器 该触发器会复制数据库中的一些数据 我想观看所有添加的内容votes user vote 结构为 我尝试的代码是 const functions require firebase func
  • 日期出现奇怪的错误,“未捕获非法访问”

    所以我试图找到最新的DateJavascript 可以处理 我把它减少到 9 月 275760 并增加了我开始捕获未捕获的天数illegal access例外new Date 09 24 275760 to new Date 10 13 2
  • Vue 和 Vuex:处理依赖的计算属性

    我的应用程序是一个使用 Vuex 在 Vue 中构建的精简电子表格 关键组件是TableCollection Table and Row The TableCollection有一个包含多个的数组Table对象 每个Table有一个包含多个
  • 代码镜像错误:未捕获错误:扩展集中无法识别扩展值([对象对象])

    全部 我目前正在从事一个React Electron项目 该项目的目标是完成一个Markdown编辑器 当我配置codemirror 该程序报告错误说 Uncaught Error Unrecognized extension value
  • 如何使用 crypto-js 解密 AES ECB

    我正在尝试将加密数据从 flash 客户端 发送到服务器端的 javascript 在 asp 中作为 jscript 运行 有几个 javascript Aes 库 但它们实际上没有文档记录 我正在尝试使用 crypto js 但无法让代
  • 在 Shopify 商店中嵌入 Vue 组件

    在产品页面中 我尝试显示自定义 Vue 组件 为简洁起见 该组件根据给定的产品 ID 显示 Firebase 数据库中的一些信息 我最初尝试将其制作为 Shopify 应用程序 以便我可以访问他们的 API 我实现了 OAuth 并且可以检
  • 如何隐藏/禁用 Highcharts.js 中的图例框?

    我想问是否可以使用 HighCharts js 库隐藏图表中的所有图例框 var chart object chart renderTo render to type graph type colors graph colors title
  • JavaScript 相对路径

    在第一个 html 文件中 我使用了一个变量类别链接 var categoryLinks Career prospects http localhost Landa DirectManagers 511 HelenaChechik Dim0
  • 如何使用asm.js进行测试和开发?

    最近我读到asm js规范 看起来很酷 但是是否有任何环境 工具来开发和测试这个工具 这还只是处于规范阶段吗 您可以尝试使用 emscripten 和 ASM JS 1 并从侧分支在 firefox 构建中运行它 有关 asm js 的链接

随机推荐

  • android.app包---------ActivityManager类介绍

    ActivityManager类介绍 ActivityManager与系统与所有正在运行Activity进行交互 相关方法介绍 getDeviceConfigurationInfo 获取设备配置属性值 getMemoryClass 返回当前
  • 编译FriendlyDesktop的Uboot源码、内核,修改开机图片logo

    1 安装依赖包 参照官网wiki教程 12章节 Nanopi 教程wiki 安装以下依赖包 sudo apt get y install bison g multilib git gperf libxml2 utils make pytho
  • mac制作ssl证书

    注意 mac 自带 openssl 所以没必要像 windows 一样先安装 openssl 直接生成即可 生成 ssl 自签名 证书 生成 key 生成rsa私钥 des3算法 server ssl key是秘钥文件名 1024位强度 o
  • 左神《直通BAT面试算法精讲课》

    左神精讲视频课 可以使用优惠码 也可以直接点进去链接购买 可以减十元 大家一起学习 共同进步 专属优惠码为 AFyqyO0 专属优惠购课链接 http www nowcoder com courses 1 coupon AFyqyO0
  • 一文带你读懂感知机的前世今生(上)

    一文带你读懂感知机的前世今生 前言 男女不分 什么是神经元 M P神经元 全或无定律 McCulloch和Pitts 一种高度简化的模型 MP神经元和真值表 MP神经元的几何理解 后记 参考 前言 男女不分 朋友 当你看到类似下图的这样一副
  • ENSP安装华为防火墙模拟器(附USG模拟设备安装包)

    1 防火墙定义 防火墙是位于两个网络中间的系统 它在这些网络之间实施访问控制策略 例如 您的系统正在连接的专用 LAN 和不安全的公共网络 它管理进出系统的进出网络的数据流量 用外行的话来说 防火墙可以被视为您网络的安全卫士 或者可以被视为
  • mybatis- useSSL=true会报错

    D Java jdk1 8 0 144 bin java exe ea Didea test cyclic buffer size 1048576 javaagent D IntelliJ IDEA 2019 3 4 lib idea rt
  • excel巧用拼接函数CONCATENATE输出JSON字符串

    使用 CONCATENATE 其中一个文本函数 将两个或多个文本字符串联接为一个字符串 在 Excel 2016 Excel Mobile 和 Excel 网页版 中 此函数已替换为 CONCAT 函数 语法 CONCATENATE tex
  • gitkraken免费版本6.5.1,Linux下载地址

    来源 https www kaisawind com 2020 03 04 2020 03 05 git gitkraken自6 5 3本地库开始收费 所以推荐下载旧版本下载地址 收费版本 version 6 5 3 url deb htt
  • 视觉架构大一统!港中文通过统一视角Container对Transformer, 深度卷积以及MLP-Mixer进行了大一统

    编辑 Happy 首发 AIWalker 前段时间MLP Mixer提出后 引发了视觉架构圈的一篇轰动 包含但不限于以下几篇文章 重参数宇宙 再添新成员 RepMLP 清华大学 旷视科技提出将重参数卷积嵌入到全连接层 新坑 谷歌提出MLP
  • 在Final Cut Pro X 中如何把音频和视频对齐?

    在拍摄的视频的时候 往往因为现场的环境嘈杂而使得录音不清晰 我们通常会单独用一个设备录音 获得单条音频 在用Final Cut Pro X剪辑上的时候 如何把音频和视频对齐呢 用Final Cut Pro X把音频和视频对齐教程 1 在事件
  • muduo_base库学习笔记6——互斥量、条件变量和倒计时门闩类

    muduo中对互斥量和条件变量的操作基本上都是调用它们对应的相关函数来实现的 例如MutexLock lock即调用pthread mutex lock Condition wait 即调用pthread cond wait等 互斥量 mu
  • C - Balanced Number HDU - 3709 (数位dp)

    题目链接 https cn vjudge net contest 278036 problem C 题目大意 手首先是T组数据 然后每一次输入两个数l r 求这个区间里面满足以某个数字为中心的两侧力矩和相等的个数 举个例子 4139 我们如
  • win10键盘锁住了怎么解决

    有win10系统用户在使用的时候 发现键盘被锁住了 导致无法使用 经过分析可能是不小心按到了键盘上的锁住键 锁定键盘的快捷键 笔记本电脑 Fn Numlock 键 第一种方法 1 外接键盘 是否按过 Numlock 键 如果按过 Numlo
  • vue2使用国际化语言vue-i18n

    1 安装 npm install vue i18n 或 yarn add vue i18n 2 引用 在main js中引用 import VueI18n from vue i18n Vue use VueI18n 运行项目 报错 由于使用
  • 网络流之最大流和最小割

    最大流问题 最大流 给定有向图中每条边的最大流量 容量 求从源点到汇点的最大流量 容量网络 括号左边代表容量 右边代表流量 残留网络 流网络中剩余可增加的流量 增广路 满足容量条件的一条流量不为零的路径 增广路定理 设容量网络G V E 的
  • 转: Windows 批处理大全

    批处理文件是无格式的文本文件 它包含一条或多条命令 它的文件扩展名为 bat 或 cmd 在命令提示下键入批处理文件的名称 或者双击该批处理文件 系统就会调用Cmd exe按照该文件中各个命令出现的顺序来逐个运行它们 使用批 处理文件 也被
  • 【云原生之Docker实战】使用Docker部署NodeBB社区平台

    云原生之Docker实战 使用Docker部署NodeBB社区平台 一 NodeBB 二 检查本地docker环境 1 检查docker版本 2 检查docker状态 3 检查docker compose版本 三 下载NodeBB镜像 四
  • 方差(variance)、标准差(Standard Deviation)、均方差、均方根值(RMS)、均方误差(MSE)、均方根误差(RMSE)

    方差 variance 衡量随机变量或一组数据时离散程度的度量 概率论中方差用来度量随机变量和其数学期望 即均值 之间的偏离程度 统计中的方差 样本方差 是每个样本值与全体样本值的平均数之差的平方值的平均数 概率论中的方差表示方法 样本方差
  • Javascript设计模式-07-观察者模式(发布订阅模式)

    Javascript设计模式 07 观察者模式 发布订阅模式 简介 观察者模式又叫发布订阅模式 他定义了一种一对多的关系 让多个观察者对象同时监听某一个主体对象 这个主体对象发生改变时就会通知所有观察者 使得他们能够自动更新自己 提供一种抽