ts实现简易观察者模式

news2024/11/20 13:32:40

什么是观察者模式

观察者模式能让你时刻知悉对象状态的变化的一种设计模式,是一种一对多依赖的关系,比如报纸的订阅

生活中随处可见的观察者模式(猎头与求职者):

headfirst设计模式气象站案例

通知更新的方式有两种: 主题推给观察者和观察者自己去主题拉取两种方式,大部分实现都采用推,这里也采用推的方式实现

气象站需要设计一个主题(Subject),它包含三个状态:气温,湿度和气压,要求主题的状态发生改变后要通知三个展示状态的布告板进行更新,要求布告板的类型是可扩展的,主题的状态是可扩展的

这里把气象站看做是一个对象,它有一些状态并且是可扩展的,这里用一个对象表示,扩展状态往里面加就行了:

type WeatherData = Partial<{
  temperature: string // 气温
  humidity: string // 湿度
  pressure: string // 气压
}>

把每个布告板看做是一个观察者,它由update(更新)和display(展示)两个功能组成,update方法是必备的且统一叫update,由气象站主题状态改变时调用update更新,这个过程就是通知更新

因为不同类型的布告板展示内容一样,所以观察者应该是一个接口

interface Observer {
  update: (data: WeatherData) => void // 更新状态
  display: (data: WeatherData) => void // 展示主题
}

主题也应该是一个接口,它包含了一些公共api:

interface Subject {
  changed: boolean // 标记状态是否更新
  observers: Observer[] // 所有观察者的集合
  setMeasurementsChanged?: (data: WeatherData) => void // 设置检测值
  measurementsChanged?: (data: WeatherData) => void // 检测值发生变化时调用通知观察者更新
  addObserver: (observer: Observer) => number // 注册观察者
  deleteObserver: (observer: Observer) => boolean // 取消订阅观察者
  notifyObservers: (data: WeatherData) => void // 通知观察者更新  推送最新状态
  setChanged: () => void // 状态变更的标记位
}

定义气象站类实现主题接口:

class Weather implements Subject {
  state: WeatherData // 记录气象站状态
  changed: boolean // 是否更新的标记位
  observers: Observer[] // 观察者集合
  constructor() {
    this.observers = [] // 初始化观察者集合
  }
  // 状态变化的钩子
  measurementsChanged(data: WeatherData) {
    console.log('气象站主题更新了,通知观察者更新--------------------')
    this.notifyObservers(data) //
  }
  // 这个方法状态有新值时供外界调用触发更新
  setMeasurementsChanged(data: WeatherData) {
    this.state = data
    // 这里可以控制更新的条件 利于条件控制状态的更新频率 比如温差超过5度或者某个字段变化了才通知更新 可以写自己的变化逻辑
    // if(data.temperature-this.state.temperature>=5) // 伪代码举例 这里的字段并不是数字类型 这里根据实际情况设计
    if (true) {
      this.setChanged(true)
    }
    this.measurementsChanged(data)
  }
  addObserver(observer: Observer) {
    return this.observers.push(observer)
  }

  deleteObserver(observer: Observer) {
    const idx = this.observers.findIndex((e) => e === observer)
    if (idx >= 0) {
      this.observers.splice(idx, 1)
      return true
    }
    return false
  }
  notifyObservers(data: WeatherData) {
    if (!this.changed) return // 如果没有更新则不通知
    // 遍历所有的观察者通知更新
    for (const observer of this.observers) {
      observer.update(data)
    }
    this.setChanged(false) // 通知更新后修改是否更新状态为false
  }
  // 设置是否有更新的标志
  setChanged(flag: boolean) {
    this.changed = flag
  }
}

有了气象站类后,实现观察者类

// 气温观察者
class TemperatureObserver implements Observer {
  update(data: WeatherData) {
    this.display(data)
  }
  display(data: WeatherData) {
    console.log('温度观察者:', data.temperature)
  }
}
// 湿度观察者
class HumidityObserver implements Observer {
  update(data: WeatherData) {
    this.display(data)
  }
  display(data: WeatherData) {
    console.log('湿度观察者:', data.humidity)
  }
}
// 气压观察者
class PressureObserver implements Observer {
  update(data: WeatherData) {
    this.display(data)
  }
  display(data: WeatherData) {
    console.log('气压观察者:', data.pressure)
  }
}

不同类型的布告板实现观察者接口定义各自的展示行为,必需实现update方法,然后往气象站添加观察者并通知更新

const subject = new Weather() // 创建气象站主题
// 添加观察者
subject.addObserver(new TemperatureObserver())
subject.addObserver(new HumidityObserver())
subject.addObserver(new PressureObserver())
// 气象站状态发生改变
subject.setMeasurementsChanged({
  temperature: '37度',
  humidity: '干燥',
  pressure: '101帕',
})
subject.setMeasurementsChanged({
  temperature: '38度',
  humidity: '滋润',
  pressure: '99帕',
})

控制台打印结果,两次状态改变成功通知更新

 以上就是一个观察模式的简易案例,原案例使用Java实现,自己理解后用ts改写,Vue的响应式原理也用到了观察者模式,知悉数据的变化通知更新页面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/159310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

年中盘点 | 2022年,PaaS 再升级

过去十五年&#xff0c;是云计算从无到有突飞猛进的十五年。PaaS 作为云计算的重要组成部分&#xff0c;在伴随着云计算高速发展的同时&#xff0c;在云计算产业链中的关键性作用日渐凸显。关于 PaaS&#xff0c;很多人都认同一个观点&#xff0c;在公有云上&#xff0c;除了 I…

【寒假每日一题】AcWing 4699. 如此编码

目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 一、题目 1、原题链接 4699. 如此编码 - AcWing题库 2、题目描述 某次测验后&#xff0c;顿顿老师在黑板上留下了一串数字 23333便飘然而去。 凝望着这个神秘数字&#xff…

雄关漫道真如铁,而今迈步从头越 | 挥别2022,再战2023!

挥别2022年 这一年&#xff0c;虽面临诸多挑战&#xff0c;但我们充满干劲儿 向下扎根&#xff0c;向上生长 这一年&#xff0c;我们风云十载&#xff0c;厚积薄发 站在2023年的开端 让我们一起回顾博云2022年的这些成绩 No.1 专精特新&#xff0c;示范引领 2022年8月&am…

【鸟哥杂谈】Linux环境搭建Redis

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-01-12 ❤️❤️ 本篇更新记录 2023-01-12 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

指针笔试题详细介绍,让你不再惧怕指针【c语言】

int main() {int a[5] { 1, 2, 3, 4, 5 };int *ptr (int *)(&a 1); //&a1的类型是int&#xff08; * &#xff09;[5]printf( "%d,%d", *(a 1), *(ptr - 1));//输出2 5 return 0; }&a&#xff0c; 取出整个数组的地址&#xff0c;放在一个数组指针中…

你拿了多少年终奖?

见字如面&#xff0c;我是军哥&#xff01;前几天我看到一个大 V 调研他的程序员粉丝&#xff0c;都拿了多少年终奖&#xff1f;结果可想而知&#xff0c;2000 多人参与问卷调查&#xff0c;53% 左右的人说今年没有年终奖。另外&#xff0c;我估计大多数人今年的年终奖金额相比…

超能面板PRO搭载北京君正研发的X2000多核异构跨界处理器

每一座建筑&#xff0c;都承载着它独特的生活方式。隐匿在老胡同里的四合院&#xff0c;见证了大院三代同堂的喧闹欢愉&#xff0c;散落在烟雨中的园林小院散发着对诗意生活的淡然向往。在一代又一代的变迁中&#xff0c;逐渐形成了符合居住者气质的生活方式。历史与现代在不断…

等差素数数列

问题描述&#xff1a; 2,3,5,7,11,13,…是素数序列。 类似&#xff1a;7,37,67,97,127,157 这样完全由素数组成的等差数列&#xff0c;叫等差素数数列。 上边的数列公差为30&#xff0c;长度为6。 2004年&#xff0c;格林与华人陶哲轩合作证明了&#xff1a;存在任意长度的素数…

事件总线 + 函数计算构建云上最佳事件驱动架构应用

作者 | 史明伟&#xff08;世如&#xff09; 距离阿里云事件总线&#xff08;EventBridge&#xff09;和 Serverless 函数计算&#xff08;Function Compute&#xff0c;FC&#xff09;宣布全面深度集成已经过去一年。站在系统元数据互通&#xff0c;产品深度集成的肩膀上&…

《面试八股文》之GitHub中文社区Java 领域又一份备战神器,开冲金三银四

今天讲讲跳槽。 新年即将开启&#xff0c;一些不满现状&#xff0c;被外界的“高薪”“好福利”吸引的人&#xff0c;一般就在这时候毅然决然地跳槽了。 跳槽是为了寻求更好的发展&#xff0c;但在跳槽前我们也不能确定下家就是更好的归宿&#xff0c;这就更加需要我们审慎地去…

前端号外—2022年明星项目居然是它,Node.js危已?

导读 | 2022年是艰难的一年&#xff0c;不仅有互联网的寒冬、还有新冠疫情的洗礼。但是似乎这一切都阻挡不了JavaScript的内卷&#xff0c;一年不长不短的时间中&#xff0c;JavaScript从创新、性能、功能等多维度深度进化&#xff0c;给前端带来了诸多惊喜。本文基于github上流…

JVM调优简介

数据类型 java虚拟机中&#xff0c;数据类型可以分为两类&#xff1a;基本类型和引用类型。 基本类型的变量保存原始值&#xff0c;即&#xff1a;它代表的值就是数值本身&#xff0c;而引用类型的变量保存引用值。 “引用值”代表了某个对象的引用&#xff0c;而不是对象本身&…

JSP内置对象详解 常用方法

目录 out request response session application exception page config pageContext JSP内置对象的作用域 JSP内置对象是在JSP运行环境中已定义好的对象&#xff0c;可在JSP页面的脚本部分直接使用。 out对象 out 为输出流对象&#xff0c;主要用于向客户端输出流…

Java-容器

一、ListArrayList<>&#xff08;变长数组&#xff09;实现add( )&#xff1a;在末尾添加一个元素clear( )&#xff1a;清空size( )&#xff1a;返回长度isEmpty( )&#xff1a;是否为空get(i)&#xff1a;获取第i个元素set(i, val)&#xff1a;将第i个元素设置为val&…

以太网接口电路设计

标准的以太网接口是这种RJ45的连接器它总共8个引脚&#xff0c;当设计成千兆以太网时&#xff0c;这8个引脚都会用到&#xff0c;大家可以看下千兆以太网引脚的信号定义&#xff0c; 0&#xff0c; 0-&#xff0c; 1&#xff0c; 1-&#xff0c; 2&#xff0c; 2-&#xff0c; …

计算机体系结构详解

文章目录1 概述1.1 计算机体系结构图1.2 计算机硬件系统图2 网工软考真题3 扩展1 概述 1.1 计算机体系结构图 1.2 计算机硬件系统图 冯 诺依曼 设计的体系结构&#xff0c;由 CPU&#xff08;运算器、控制器&#xff09;、存储器、输入/输出设备&#xff08;I/O&#xff09;…

Windows同时安装两个版本JDK,并实现动态切换版本JDK8和JAVA17教程

一、下载安装两个版本的JDK 官网下载地址&#xff1a;Java Downloads | Oracle 下载版本 jdk1.8.0_271 和 jdk-17.0.5 下载安装成功后&#xff0c;安装路径E:\Java\上 JDK8 有两个包一个jdk1.8.0_271&#xff0c;一个jre1.8.0_271。JDK17只有一个jdk-17.0.5 二、JDK的环境配…

图的最小生成树

文章目录最小生成树的概念Prim算法邻接表邻接矩阵验证PrimKruskal算法邻接表邻接矩阵验证Kruskal源代码邻接表邻接矩阵最小生成树的概念 最小生成树(Minimum Spanning Tree) : 在加权连通图(连通网)的所有生成树中, 各边权值之和最小的生成树, 称为最小生成树. 该定义是在无向…

strapi系列-如何去除接口里的attributes以及 data key,配置关联数据等

我们先来创建一个接口&#xff0c;然后看一下正常接口返回的数据格式是什么样子 创建表以及字段 添加一条数据 配置接口权限 我暂时给了这个接口PUBLIC权限&#xff0c;用来测试 使用postman进行接口测试 我们可以看到&#xff0c;这里被包了一层attributes&#xff0c;如…

密码学_ZUC算法

目录 ZUC算法介绍 算法结构 线性反馈移位寄存器LFSR LFSR初始化模式 LFSR工作模式 比特重组BR 非线性函数F 加密流程 ZUC算法介绍 祖冲之算法集&#xff08;ZUC算法&#xff09;是由我国学者自主设计的加密和完整性算法&#xff0c;包括祖冲之算法、加密算法128-EEA3和完整…