当前位置: 首页 > news >正文

JavaScript之观察者模式

本文作者为 360 奇舞团前端开发工程师

概述

在日常开发中,开发人员经常使用设计模式来解决软件设计中的问题。其中,观察者模式是一种常用的模式,它可以帮助开发人员更好地处理对象之间的通信。在 JavaScript 中,观察者模式的应用非常广泛,可以用于实现事件处理、数据绑定等功能。本文将介绍观察者模式的基本概念和实现方式。

什么是观察者模式?

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象(observer)同时监听某一个主题对象(subject)。当主题对象发生变化时,它会自动通知所有的观察者对象,使它们能够及时更新自己的状态。

观察者模式的优点在于它可以实现对象之间的松耦合,使得 Subject 和 Observer 可以独立地变化,而不会相互影响。它还可以提高代码的复用性和可维护性,使得代码更加清晰和易于理解。

事件观察者

该模式的视图如下所示:

EventObserver
│ 
├── subscribe: 添加新的可观察事件
│ 
├── unsubscribe: 移除可观察事件
|
└── broadcast: 执行带有绑定数据的所有事件

首先要执行初始化EventObserver操作:

class EventObserver {constructor() {this.observers = [];}
}

从观察到的事件的空列表开始,并对每个新实例执行此操作。

订阅方法

要添加新事件,请执行以下操作:

subscribe(fn) {this.observers.push(fn);
}

获取观察到的事件列表并将新项目推送到数组中,事件列表是回调函数列表。

要测试这个方法,请执行以下操作:

const fn = () => {};observer.subscribe(fn);// Assert
assert.strictEqual(observer.observers.length, 1);

取消订阅方法

要删除事件,请执行以下操作:

unsubscribe(fn) {this.observers = this.observers.filter((subscriber) => subscriber !== fn);
}

从列表中过滤掉与回调函数匹配的内容。如果没有匹配,回调将保留在列表中,过滤器返回一个新列表并重新分配观察者列表。

要测试这个方法,请执行以下操作:

const observer = new EventObserver();
const fn = () => {};observer.subscribe(fn);observer.unsubscribe(fn);// Assert
assert.strictEqual(observer.observers.length, 0);

回调必须与列表中的相同函数匹配,如果存在匹配项,取消订阅方法会将其从列表中删除。

广播法

要调用所有事件,请执行以下操作:

broadcast(data) {this.observers.forEach((subscriber) => subscriber(data));
}

这会遍历观察到的事件列表并执行所有回调。这样,你就可以获得与订阅事件必要的一对多关系,传入data是回调数据绑定的参数。

要测试这个方法,请执行以下操作:

const observer = new EventObserver();let subscriberHasBeenCalled = false;
const fn = (data) => subscriberHasBeenCalled = data;observer.subscribe(fn);observer.broadcast(true);// Assert
assert(subscriberHasBeenCalled);

使用 let 而不是 const 这样我们就可以更改变量的值,这使得变量可变,然后允许我在回调内部重新分配它的值。let 在代码中会向其他程序员发送一个信号,表明该变量在某个时刻正在发生变化,这样就增加了 JavaScript 代码的可读性和清晰度。

好了,我们已经学会了一个简单的观者模式在 javaScript 中的实现。

总结

这篇主要简单介绍了观察者模式和其简单的实现,设计模式还有很多种,例如:单例模式、策略模式、工厂模式等,我们的核心目的是要学习其思想,而不是死记硬背每一种模式的实现方式。只有理解了设计模式的思想,才能在各种业务场景中灵活地应用它们。

参考链接

https://www.digitalocean.com/community/tutorial-series/javascript-design-patterns

https://developer.mozilla.org/zh-CN/docs/learn/JavaScript https://zhuanlan.zhihu.com/p/77275289

- END -

关于奇舞团

奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

5595bc0d25fbd65096e211041be78d7e.png

相关文章:

JavaScript之观察者模式

本文作者为 360 奇舞团前端开发工程师 概述 在日常开发中,开发人员经常使用设计模式来解决软件设计中的问题。其中,观察者模式是一种常用的模式,它可以帮助开发人员更好地处理对象之间的通信。在 JavaScript 中,观察者模式的应用非…...

深入了解ln命令:创建硬链接和符号链接的实用指南

文章目录 1. 引言1.1 关于ln命令1.2 ln命令的作用和用途 2. 基本用法2.1 创建硬链接2.2 创建符号链接2.3 区别硬链接和符号链接 3. 操作示例3.1 创建硬链接的示例3.2 创建符号链接的示例3.3 查看链接信息 4. 注意事项和常见问题4.1 文件路径4.2 软链接的相对路径4.3 软链接的更…...

虚拟IP技术

1.说明 虚拟IP(Virtual IP Address,简称VIP)是一个未分配给真实弹性云服务器网卡的IP地址。 弹性云服务器除了拥有私有IP地址外,还可以拥有虚拟IP地址,用户可以通过其中任意一个IP(私有IP/虚拟IP&#xf…...

蓝桥杯 题库 简单 每日十题 day5

01 字符计数 字符计数 题目描述 给定一个单词,请计算这个单词中有多少个元音字母,多少个辅音字母。 元音字母包括a,e,i,o,u,共五个,其他均为辅音字母。 输入描述 输入格式: 输入一行&#xff0…...

【计算机网络】图解路由器(一)

图解路由器(一) 1、什么是路由器?2、什么是路由选择?3、什么是转发?4、路由器设备有哪些类型?5、根据性能分类,路由器有哪些类型?5.1 高端路由器5.2 中端路由器5.3 低端路由器 6、什…...

C语言文件的相关操作

C语言中文件的相关操作 文件的打开 使用文件的打开函数需要引入这个头文件&#xff1a;#include <fcntl.h> open函数 int open(char const *pathname, int flags, mode_t mode) 功能&#xff1a;打开已有的文件或者创建新文件参数 pathname&#xff1a;文件路径名&…...

Java入门级简单定时任务TimerTask

如果要执行一些简单的定时器任务&#xff0c;无须做复杂的控制&#xff0c;也无须保存状态&#xff0c;那么可以考虑使用JDK 入门级的定期器Timer来执行重复任务。 一、原理 JDK中&#xff0c;定时器任务的执行需要两个基本的类&#xff1a; java.util.Timer; java…...

Linux命令行教程:使用head和tail命令快速查看文件的开头和结尾

文章目录 简介A. 什么是head和tail命令B. head和tail命令的作用和用途 head命令A. 命令格式和语法B. 常见选项和参数1. -n&#xff1a;指定显示的行数2. -c&#xff1a;指定显示的字节数3. -v&#xff1a;显示文件名 C. 示例和应用实例1. 显示文件的前几行2. 显示多个文件的前几…...

[CISCN 2019 初赛]Love Math 通过进制转换执行命令

目录 hex2bin bin2hex base_convert 动态函数 第一种解法 通过get获取参数 绕过 第二种解法 读取请求头 getallheaders echo a,b 第三种解法 异或获得更多字符 这道题也是很有意思&#xff01; 通过规定白名单和黑名单 指定了 函数为数学函数 并且参数也只能是规…...

【Linux】系统编程生产者消费者模型(C++)

目录 【1】生产消费模型 【1.1】为何要使用生产者消费者模型 【1.2】生产者消费者模型优点 【2】基于阻塞队列的生产消费者模型 【2.1】生产消费模型打印模型 【2.2】生产消费模型计算公式模型 【2.3】生产消费模型计算公式加保存任务模型 【2.3】生产消费模型多生产多…...

【数据结构】图的应用:最小生成树;最短路径;有向无环图描述表达式;拓扑排序;逆拓扑排序;关键路径

目录 1、最小生成树 1.1 概念 1.2 普利姆算法&#xff08;Prim&#xff09; 1.3 克鲁斯卡尔算法&#xff08;Kruskal&#xff09; 2、最短路径 2.1 迪杰斯特拉算法&#xff08;Dijkstra&#xff09; 2.2 弗洛伊德算法&#xff08;Floyd&#xff09; 2.3 BFS算法&…...

大数据驱动业务增长:数据分析和洞察力的新纪元

文章目录 大数据的崛起大数据的特点大数据技术 大数据驱动业务增长1. 洞察力和决策支持2. 个性化营销3. 风险管理4. 产品创新 大数据分析的新纪元1. 云计算和大数据示例代码&#xff1a;使用AWS的Elastic MapReduce&#xff08;EMR&#xff09;进行大数据分析。 2. 人工智能和机…...

科技云报道:分布式存储红海中,看天翼云HBlock如何突围?

科技云报道原创。 过去十年&#xff0c;随着技术的颠覆性创新和新应用场景的大量涌现&#xff0c;企业IT架构出现了稳态和敏态的混合化趋势。 在持续产生海量数据的同时&#xff0c;这些新应用、新场景在基础设施层也普遍基于敏态的分布式架构构建&#xff0c;从而对存储技术…...

Java高级-动态代理

动态代理 1.介绍2.案例 1.介绍 public interface Star {String sing(String name);void dance(); }public class BigStar implements Star{private String name;public BigStar(String name) {this.name name;}public String sing(String name) {System.out.println(this.name…...

时序预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络时间序列预测

时序预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短…...

n个不同元素进栈,求出栈元素的【不同排列】以及【排列的数量】?

我在网上看的博客大部分是告诉你这是卡特兰数&#xff0c;然后只给出了如何求解有多少种排列&#xff0c;没有给出具体排列是怎么样的。如果你还不知道卡特兰数&#xff0c;请查看&#xff1a;https://leetcode.cn/circle/discuss/lWYCzv/ 这里记录一下如何生成每种具体的排列…...

Python中TensorFlow的长短期记忆神经网络(LSTM)、指数移动平均法预测股票市场和可视化...

原文链接&#xff1a;http://tecdat.cn/?p23689 本文探索Python中的长短期记忆&#xff08;LSTM&#xff09;网络&#xff0c;以及如何使用它们来进行股市预测&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 相关视频 在本文中&#xff0c;你将看到如何使用…...

多线程的学习第二篇

多线程 线程是为了解决并发编程引入的机制. 线程相比于进程来说,更轻量 ~~ 更轻量的体现: 创建线程比创建进程,开销更小销毁线程比销毁进程,开销更小调度线程比调度进程,开销更小 进程是包含线程的. 同一个进程里的若干线程之间,共享着内存资源和文件描述符表 每个线程被独…...

git之撤销工作区的修改和版本回溯

有时候在工作区做了一些修改和代码调试不想要了,可如下做 (1)步骤1:删除目录代码,确保.git目录不能修改 (2)git log 得到相关的commit sha值 可配合git reflog 得到相要的sha值 (3)执行git reset --hard sha值,可以得到时间轴任意版本的代码 git reset --hard sha值干净的代…...

sed awk使用简介

简介 本文主要介绍 Linux 系统的两个神级工具&#xff1a;sed 和 awk &#xff0c;他们是Linux高手们必备的技能&#xff0c;很值得我们去研究的东西。 这里是我在网上书上收集的相关资料&#xff0c;因为这两个工具很有名也很重要&#xff0c;所以这些资料会帮助我更好的了解…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

Modbus RTU与Modbus TCP详解指南

目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…...

shell脚本质数判断

shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数&#xff09;shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数&#xff09; 思路&#xff1a; 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...