前端开发的观察者模式

devtools/2024/12/22 9:01:01/

什么是观察者设计模式

观察者模式(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 模式的一个简单实现。

总结

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

 


http://www.ppmy.cn/devtools/112073.html

相关文章

微服务CI/CD实践(五)Jenkins Docker 自动化构建部署Java微服务

微服务CI/CD实践系列: 微服务CI/CD实践(一)环境准备及虚拟机创建 微服务CI/CD实践(二)服务器先决准备 微服务CI/CD实践(三)Jenkins部署及环境配置 微服务CI/CD实践(四)…

QT QTcpSocket作为客户端

前言 QTcpSocket是Qt提供的关于TCP网络通信的类。QTcpSocket是一个异步的类,能够非阻塞式发送和接收数据。QTcpSocket内部封装了网络通信相关细节,对外提供便利的接口去帮助开发人员实现简历连接、断开连接、数据收发。 主要内容 基本使用方式 项目文…

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"in…

综合案例-数据可视化-折线图

一、json数据格式 1.1 json数据格式的定义与功能 json是一种轻量级的数据交互格式&#xff0c;可以按照json指定的格式去组织和封装数据&#xff0c;json数据格式本质上是一个带有特定格式的字符串。 功能&#xff1a;json就是一种在各个编程语言中流通的数据格式&#xff0…

828华为云征文 | Flexus X 实例服务器网络性能深度评测

引言 随着互联网应用的快速发展&#xff0c;网络带宽和性能对云服务器的表现至关重要。在不同的云服务平台上&#xff0c;即便配置相同的带宽&#xff0c;实际的网络表现也可能有所差异。因此&#xff0c;了解并测试服务器的网络性能变得尤为重要。本文将以华为云X实例服务器为…

yolov8 rect batch_shapes 672 图像大小变化

遇到这样一种情况&#xff1a;img_sz640,但在val时&#xff0c;输入网络的张量h和w是672 为什么输入图像会从640变大到672&#xff1f; 这是因为一种rectangle增强方法&#xff0c;“同个batch里做rectangle宽高等比变换&#xff0c; 加快训练 &#xff0c;对于多余的黑边做到…

Redis 入门 - 五大基础类型及其指令学习

经过前面Redis入门系列三篇文章学习&#xff0c;相信大家已经准备好学习新知识了&#xff0c;到这里也算是真正开始学习Redis了。学习了软件安装&#xff0c;客户端选择&#xff0c;那么接下来也应该来了解Redis有什么&#xff0c;能干什么。 我们在第一章中就说过&#xff0c…

[M滑动窗口] lc 2555. 两个线段获得的最多奖品(滑动窗口+同向双指针+代码技巧)

文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接&#xff1a;2555. 两个线段获得的最多奖品 2. 题目解析 挺有意思的一道题目&#xff0c;同向双指针简单dp 的思想。 思路&#xff1a; 题目要求枚举两个线段&#xff0c;其实可以想到经典题目「两数之和」。我们可以枚举…