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

前端开发的观察者模式

什么是观察者设计模式

观察者模式(Observer Pattern)是前端开发中常用的一种设计模式。它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,其所有依赖对象都能收到通知并自动更新。观察者模式广泛应用于事件驱动的系统,如浏览器事件、发布-订阅系统,以及各类框架的状态管理机制。

观察者设计模式定义了一种 一对多 的依赖关系,当 一个对象的状态发生变化 时,所有依赖它的对象都会自动收到通知。这种模式可以解耦观察者和被观察者,使得它们可以独立变化。

观察者模式的关键角色:

  1. Subject(被观察者): 负责维护观察者列表,并在自身状态发生变化时通知所有观察者。
  2. Observer(观察者): 订阅目标的变化,并在收到通知时执行相关操作。

观察者模式的实现

1. 简单观察者模式

// 观察者接口
interface Observer {update(state: string): void;
}// 被观察者
class Subject {private observers: Observer[] = [];private state: string = '';// 添加观察者public attach(observer: Observer): void {this.observers.push(observer);}// 移除观察者public detach(observer: Observer): void {this.observers = this.observers.filter(obs => obs !== observer);}// 通知所有观察者public notify(): void {this.observers.forEach(observer => observer.update(this.state));}// 改变状态并通知观察者public setState(state: string): void {this.state = state;this.notify();}
}// 具体的观察者
class ConcreteObserver implements Observer {private name: string;constructor(name: string) {this.name = name;}// 收到通知时的动作public update(state: string): void {console.log(`${this.name} received update: ${state}`);}
}// 测试观察者模式
const subject = new Subject();const observer1 = new ConcreteObserver('Observer 1');
const observer2 = new ConcreteObserver('Observer 2');subject.attach(observer1);
subject.attach(observer2);subject.setState('State A');
subject.setState('State B');

在这个例子中,我们实现了基本的观察者模式:一个 Subject 类可以被多个 Observer 观察,每当 Subject 的状态发生变化时,它会通知所有观察者。

2. 发布-订阅模式

发布-订阅模式(Publish-Subscribe Pattern) 是观察者模式的一种变体,通常通过事件系统来实现。发布者不直接通知观察者,而是通过中介(消息中心)将事件广播出去,由订阅者选择性地接收。

// 消息中心
class EventEmitter {private events: { [key: string]: Function[] } = {};// 订阅事件public subscribe(event: string, listener: Function): void {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(listener);}// 发布事件public publish(event: string, data?: any): void {if (this.events[event]) {this.events[event].forEach(listener => listener(data));}}// 取消订阅public unsubscribe(event: string, listener: Function): void {if (this.events[event]) {this.events[event] = this.events[event].filter(l => l !== listener);}}
}// 测试发布-订阅模式
const eventEmitter = new EventEmitter();const handler = (data: any) => console.log('Event received:', data);// 订阅事件
eventEmitter.subscribe('eventA', handler);// 发布事件
eventEmitter.publish('eventA', { message: 'Hello, World!' });// 取消订阅
eventEmitter.unsubscribe('eventA', handler);

在发布-订阅模式中,发布者和订阅者是通过 EventEmitter 消息中心进行通信的,发布者无需知道订阅者的存在,这使得它们之间的耦合度进一步降低。

3. 双向绑定模式(MVVM)

MVVM(Model-View-ViewModel) 是一种常见的双向绑定模式,在前端框架如 VueAngular 中很常见。它通过数据绑定使得 ViewModel 可以双向通信,通常是通过一个 ViewModel 来桥接二者。

// ViewModel
class ViewModel {private state: string = '';private observers: Function[] = [];// 获取当前状态public getState(): string {return this.state;}// 设置状态并通知视图更新public setState(newState: string): void {this.state = newState;this.notify();}// 添加视图更新的回调public bind(observer: Function): void {this.observers.push(observer);}// 通知视图更新private notify(): void {this.observers.forEach(observer => observer(this.state));}
}// 视图更新函数
const updateView = (state: string) => {console.log('View updated:', state);
};// 测试双向绑定
const viewModel = new ViewModel();
viewModel.bind(updateView);viewModel.setState('New State');
console.log('Current State:', viewModel.getState());

在这个例子中,ViewModel 充当了模型和视图之间的桥梁,确保视图在数据更新时及时反应。这是 MVVM 模式的一个简单实现。

总结

观察者设计模式及其变体在前端开发中起着至关重要的作用。通过观察者模式,可以解耦对象之间的直接依赖关系,从而提升系统的灵活性和可维护性。无论是基础的观察者模式,还是更为复杂的发布-订阅模式、双向绑定模式,都在不同的场景中发挥了不可替代的作用。

 

相关文章:

前端开发的观察者模式

什么是观察者设计模式 观察者模式(Observer Pattern)是前端开发中常用的一种设计模式。它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,其所有依赖对象都能收到通知并自动更新。观察者模式广泛应用于事件驱动的系…...

Pycharm 输入三个引号没有自动生成函数(方法)注释

配置项路径:pycharm–>Settins–>Tools–>Python Integrated Tools–>Docstrings–>Docstrings format选择对应的工程,如果有多个工程的话将 Docstrings format 的值从 Plain 换成 reStructuredText...

lammps后处理:多帧孔洞体积和孔隙率的计算

本文介绍lammps后处理技巧:多帧孔洞体积和孔隙率的计算方法。 在前面的专栏中,已经介绍了单帧孔洞体积的计算方法,有不少粉丝朋友咨询多帧孔洞体积的计算方法。 在上一次案例代码的基础上,稍加修改,添加一个for循环遍历所有的帧即可实现多帧孔洞体积的计算。 计算的结果…...

免费且实用:UI设计常用的颜色参考网站和一些Icon设计网站

用心去分享!请给我点个关注和点赞收藏!谢谢各位努力的人才! 1.在UI设计的时候,没有灵感,怎么办?可以参考这个网站(需要魔法能量) 网址如下: Color Hunt - Color Palette…...

log4j日志封装说明—slf4j对于log4j的日志封装-正确获取调用堆栈

日志是项目中必用的东西,日志产品里最普及应该就是log4j了。(logback这里暂不讨论。) 先看一下常用的log4j的用法,一般来说log4j都会配合slf4j或者common-logging使用,这里已slf4j为例。添加gradle依赖: dependencies { compile(l…...

JVM面试真题总结(六)

文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 解释GC的标记-整理算法及其优点 GC(垃圾收集&#xff…...

C语言代码练习(第十八天)

今日练习: 48、猴子吃桃问题。猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时&…...

linux上使用rpm的方式安装mysql

1.从mysql官网上下载需要的版本,根据操作系统版本,CPU架构,下载让rpm bundle,这个版本是个完整版,包含其他所有版本 上传到服务器的一个目录,进行解压 执行tar -xvf mysql*.tar tar -xvf mysql*.tar 2.卸载老版本m…...

html 中如何使用 uniapp 的部分方法

示例代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><…...

Samtec连接器小课堂 | 连接器电镀常识QA

【摘要/前言】 像大多数电子元件一样&#xff0c;无数子元件和工艺的质量直接影响到成品的质量和性能。对于PCB级连接器&#xff0c;这些因素包括针脚材料、塑料类型、模制塑料体的质量、尾部的共面性、表面处理&#xff08;电镀&#xff09;的质量、选择正确的连接器电镀、制…...

大模型备案全网最详细流程解读(附附件+重点解读)

文章目录 一、语料安全评估 二、黑盒测试 三、模型安全措施评估 四、性能评估 五、性能评估 六、安全性评估 七、可解释性评估 八、法律和合规性评估 九、应急管理措施 十、材料准备 十一、【线下流程】大模型备案线下详细步骤说明 十二、【线上流程】算法备案填报…...

基于2143规则编码的uint8_t如何转换成float

2143格式存储的float类型数据在解码时&#xff0c;需要将1和2互换&#xff0c;3和4互换&#xff0c;然后 通过数组转float&#xff0c;进行转换 uint8_t data[] {0x72, 0x02, 0xc8, 0x42}; // 字节数组 float bytesToFloat(uint8_t data[]) { uint32_t x; memcpy(&x, da…...

[项目][WebServer][整体框架设计]详细讲解

目录 0.框架 && 前言1.TcpServer类1.功能2.类设计 2.HttpServer类1.功能2.类设计 3.Request类 && Response类1.功能2.Request类设计3.Response类设计 4.EndPoint类1.功能2.类设计 5.Task类1.功能2.类设计 6.ThreadPool类1.功能2.类设计 0.框架 && 前言…...

SprinBoot+Vue网上购物商城的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…...

【数据结构】2——二叉树遍历

数据结构2——二叉树遍历 单纯记录 文章目录 数据结构2——二叉树遍历一、二叉树遍历1&#xff0c;先序遍历&#xff1a;根左右递归实现非递归实现&#xff08;栈&#xff09; 2.中序遍历&#xff1a;左根右递归非递归 3 .后序遍历&#xff1a;左右根递归非递归&#xff08;两…...

数据结构应用实例(五)——关键路径

Content: 一、问题描述二、算法思想三、代码实现四、小结 一、问题描述 设计实现 AOE 网的关键活动与关键路径问题&#xff1b; 二、算法思想 获取拓扑序列&#xff1b;计算节点的最早开始时间 v e [ i ] ve[i] ve[i]&#xff1b;计算节点的最晚开始时间 v l [ j ] vl[j] v…...

组播 2024 9 11

PIM&#xff08;Protocol Independent Multicast&#xff09;是一种常用的组播路由协议&#xff0c;其独立于底层的单播路由协议&#xff0c;能够在多种网络环境中有效地实现多播路由功能。PIM主要有两种模式&#xff1a;PIM Sparse Mode (PIM-SM) 和 PIM Dense Mode (PIM-DM)&…...

揭秘开发者的效率倍增器:编程工具的选择与应用

文章目录 每日一句正能量前言工具介绍功能特点&#xff1a;使用场景&#xff1a;提高工作效率的方式&#xff1a; 效率对比未来趋势后记 每日一句正能量 这推开心窗之人&#xff0c;可以是亲朋好友&#xff0c;也可以是陌客路人&#xff0c;可以是德高望重的哲人名流&#xff0…...

在AI的时代,程序员如何才不被淘汰

随着人工智能技术的迅猛发展&#xff0c;大模型&#xff08;Large Language Models, LLMs&#xff09;正逐渐成为IT行业的热点。对于程序员来说&#xff0c;转行大模型领域不仅意味着新的机遇&#xff0c;也面临着诸多挑战。本文将探讨程序员转行大模型的机遇与挑战&#xff0c…...

tabBar设置底部菜单选项以及iconfont图标,setTabBar设置TabBar和下拉刷新API

tabBartabBar属性:设置底部 tab 的表现 ​ ​ ​ ​ 首先在pages.json页面写一个tabBar对象,里面放入list对象数组,里面至少要有2个、最多5个 tab, 如果只有一个tab的话,H5(浏览器)依然可以显示底部有一个导航栏,如果没有,需要重启后才有,小程序则报错,只有2个以上才可以…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...