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

设计模式——观察者模式

文章目录

  • 1 概述
  • 2 实现
  • 3 总结

1 概述

观察者模式可以分为观察者和被观察者,观察者通过注册到一个被观察者中,也可视为订阅,当被观察者的数据发生改变时,会通知到观察者,观察者可以据此做出反应。
可以类比订阅报纸,报社就是被观察者,订阅者就是观察者,订阅者通过订阅报纸与报社建立联系,而报社有新报纸则主动投递给订阅者。

2 实现

这里以Head First 设计模式中的观察者模型为例。
在这里插入图片描述
讲的是一个气象监测站模型,气象站有三个传感器,分别采集温度、湿度和气压三个值。气象站采集完数据之后会将数据设置到WeatherData对象中,而WeatherData数据更新后需要同时将数据更新到三个显示装置中。
这里就是使用了观察者模式,WeatherData是数据中心,是被观察者,而显示装置则是观察者,当观察者订阅之后,数据中心的变化都会主动通知到观察者。
这个模型的类图如下:
在这里插入图片描述
其中最重要的就是Subject和Observer接口,这里Subject就是被观察者的总接口,而Observer接口则是观察者总接口。Display接口则是因为多个显示器都拥有共同的Display行为。
WeatherData实现Subject,成为一个具体的Subject,而三个Display则实现Observer接口,成为观察者实例。
下面是代码实例:
Subject接口

public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}

拥有对Observer对象操作的注册和删除操作,也有通知各个Observer的方法。
Observer接口

public interface Observer {void update(float temperature, float humidity, float pressure);
}

观察者接口,拥有Observer的公用操作,Subject通过该接口来更新各个Observer中的数据。被观察者其实就是通过这个接口来通知到各个观察者的
DisplayElement接口

public interface DisplayElement {public void display();
}

各个Display的公用方法
WeatherData类

public class WeatherData implements Subject {private List<Observer> observers;private float temperature;private float humidity;private float pressure;public WeatherData() {observers = new ArrayList<Observer>();}public void registerObserver(Observer o) {observers.add(o);}public void removeObserver(Observer o) {observers.remove(o);}public void notifyObservers() {for (Observer observer : observers) {observer.update(temperature, humidity, pressure);}}public void measurementsChanged() {notifyObservers();}public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}public float getTemperature() {return temperature;}public float getHumidity() {return humidity;}public float getPressure() {return pressure;}}

具体的被观察者类,会有一个存有所有观察者对象的集合,当数据变化时,会遍历这个集合来通知观察者,而通知就是调用观察者的update方法。
ForecastDisplay类

public class ForecastDisplay implements Observer, DisplayElement {private float currentPressure = 29.92f;  private float lastPressure;private WeatherData weatherData;public ForecastDisplay(WeatherData weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);}public void update(float temp, float humidity, float pressure) {lastPressure = currentPressure;currentPressure = pressure;display();}public void display() {System.out.print("Forecast: ");if (currentPressure > lastPressure) {System.out.println("Improving weather on the way!");} else if (currentPressure == lastPressure) {System.out.println("More of the same");} else if (currentPressure < lastPressure) {System.out.println("Watch out for cooler, rainy weather");}}
}

这是三个具体的观察者其中的一个,实现了Observer接口,并持有WeatherData对象,在ForecastDisplay对象创建的时候,会将自己加到WeatherData被观察者对象的集合中保存。当数据变化时,WeatherData会从集合中遍历到这个对象,并调用其update方法。
其他三个观察者类似。
测试代码:

public class WeatherStation {public static void main(String[] args) {WeatherData weatherData = new WeatherData();CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);weatherData.setMeasurements(80, 65, 30.4f);weatherData.setMeasurements(82, 70, 29.2f);weatherData.setMeasurements(78, 90, 29.2f);weatherData.removeObserver(forecastDisplay);weatherData.setMeasurements(62, 90, 28.1f);}
}

三个观察者显示器获取到了同样的更新数据,但是他们可以根据自身的显示逻辑来做出不同的显示结果

Current conditions: 80.0F degrees and 65.0% humidity
Avg/Max/Min temperature = 80.0/80.0/80.0
Forecast: Improving weather on the way!
Current conditions: 82.0F degrees and 70.0% humidity
Avg/Max/Min temperature = 81.0/82.0/80.0
Forecast: Watch out for cooler, rainy weather
Current conditions: 78.0F degrees and 90.0% humidity
Avg/Max/Min temperature = 80.0/82.0/78.0
Forecast: More of the same
Current conditions: 62.0F degrees and 90.0% humidity
Avg/Max/Min temperature = 75.5/82.0/62.0Process finished with exit code 0

3 总结

  1. 观察者加被观察者组成观察者模式
  2. 观察者继承Observer接口,该接口提供一个通知观察者的方法
  3. 观察者持有被观察者的引用,在构造方法中调用被观察者的注册方法将自身注册为一个观察者
  4. 被观察者拥有一个观察者集合,用于存储所有注册的观察者的对象
  5. 观察者可以自己调用注册和注销方法将自身添加到被观察者的列表中或从列表中移除
  6. 被观察者要通知观察者时,遍历观察者集合,调用观察者接口中的方法通知观察者

相关文章:

设计模式——观察者模式

文章目录 1 概述2 实现3 总结 1 概述 观察者模式可以分为观察者和被观察者&#xff0c;观察者通过注册到一个被观察者中&#xff0c;也可视为订阅&#xff0c;当被观察者的数据发生改变时&#xff0c;会通知到观察者&#xff0c;观察者可以据此做出反应。 可以类比订阅报纸&am…...

在Debian 12 上安装 PHP 5.6, 7.4

环境&#xff1a;Debian 12 Debian 12 默认的PHP版本为 8.2 如果直接安装php7.4就出现下面的报错&#xff1a; sudo apt-get install libapache2-mod-php7.4 php7.4 php7.4-gd php7.4-opcache php7.4-mbstring php7.4-xml php7.4-json php7.4-zip php7.4-curl php7.4-imap p…...

微服务——统一网关Getway

为什么需要网关&#xff1f; 网关的两种实现: 网关Getway——快速入门 步骤一 网关背身也是一个微服务&#xff0c;需要注册到nacos中去 步骤二 成功运行后 可以通过网关进行请求转发到对应服务。 流程如下&#xff1a; 路由断言工厂 网关路由可以配置的东西有如下。 spri…...

[ELK安装篇]:基于Docker虚拟容器化(主要LogStash)

文章目录 一&#xff1a;前置准备-(参考之前博客)&#xff1a;1.1&#xff1a;准备Elasticsearch和Kibana环境&#xff1a;1.1.1&#xff1a;地址&#xff1a;https://blog.csdn.net/Abraxs/article/details/128517777 二&#xff1a;Docker安装LogStash(数据收集引擎&#xff…...

纪录片《打铁文艺社》:从全美高中生电影节到多项国际赞誉,聚焦城市公共艺术的蜕变之路

7月21日&#xff0c;在全美高中生电影节&#xff08;All American High School Film Festival&#xff0c;AAHSFF&#xff09;公布的入围名单中&#xff0c;一部取材于中国深圳的纪录片《打铁文艺社Datie: The Art Tribe of Tiegang》以其深刻的主题和精良的制作&#xff0c;引…...

VLAN---虚拟局域网

VLAN— 虚拟局域网 LAN—局域网 MAN—城域网 WAN—广域网 1.一个VLAN相当于是一个广播域 VLAN—通过路由器和交换机协同工作后&#xff0c;将原本的一个广播域逻辑上&#xff0c;拆 分为多个虚拟的广播域。 VLAN配置&#xff1a; 1.创建VLAN VID—VLAN ID------用来区分和…...

新的CoolSiC™槽沟MOSFET技术,用于低栅氧化物应力和高性能

标题&#xff1a;The new CoolSiC™ Trench MOSFET Technology for Low Gate Oxide Stress and High Performance UPS&#xff08;Uninterruptible Power Supply&#xff09;系统也称不间断电源系统&#xff0c;是一种能够提供电力备用的设备&#xff0c;当主电源出现故障或停…...

【开源项目】低代码数据可视化开发平台-Datav

Datav 基本介绍 Datav是一个Vue3搭建的低代码数据可视化开发平台&#xff0c;将图表或页面元素封装为基础组件&#xff0c;无需编写代码即可完成业务需求。 它的技术栈为&#xff1a;Vue3 TypeScript4 Vite2 ECharts5 Axios Pinia2 在线预览 账号: admin 密码: 123123预…...

【自动话化运维】Ansible常见模块的运用

目录 一、Ansible简介二、Ansible安装部署2.1环境准备 三、ansible 命令行模块3.1&#xff0e;command 模块3.2&#xff0e;shell 模块3.3&#xff0e;cron 模块3.4&#xff0e;user 模块3.5&#xff0e;group 模块3.6&#xff0e;copy 模块3.7&#xff0e;file 模块8&#xff…...

深入理解C语言中的字符指针初始化与用法

字符指针初始化 - C 语言详解 目录 1. 介绍 2. 字符指针初始化的基础 3. 使用 const 关键字的字符指针初始化 4. C 语言与 C 在字符指针初始化的差异 5. 常见陷阱与最佳实践 6. 进阶概念&#xff1a;指针算术与动态内存分配 7. 字符串函数与字符指针 8. 结论介绍 在 C 语言中…...

es添加索引命令行和浏览器添加索引--图文详解

一、添加索引 创建索引 curl -X PUT "localhost:9200/my-index-00001?pretty" 获取索引 curl -X GET "localhost:9200/my-index-000001?pretty" 获取全部的索引 curl -X GET "http://localhost:9200/_cat/indices?v" 获取索引映射 cur…...

Java 大数字运算之 BigDecimal 类

在 Java 中提供了用于大数字运算的类&#xff0c;即 java.math.BigInteger 类和 java.math.BigDecimal 类。这两个类用于高精度计算&#xff0c;其中 BigInteger 类是针对整型大数字的处理类&#xff0c;而 BigDecimal 类是针对大小数的处理类。今天主要讲一下 BigDecimal 类 …...

MySQL 8.0 OCP (1Z0-908) 考点精析-架构考点1:二进制日志文件(Binary log)

文章目录 MySQL 8.0 OCP (1Z0-908) 考点精析-架构考点1&#xff1a;二进制日志文件&#xff08;Binary log&#xff09;MySQL二进制日志&#xff08;Binary log&#xff09;二进制日志文件的相关配置二进制日志文件的相关参数的说明二进制日志的格式设置二进制日志的格式 二进制…...

MY.CNF

# [client] port 3306 socket /var/lib/mysql/mysql.sock [mysql] prompt "\umysqldb \R:\m:\s [\d]> " no_auto_rehash loose-skip-binary-as-hex [mysqld] user mysql port 3306 #主从复制或MGR集群中&#xff0c;server_id记得要不同 #另外…...

SpringBoot IOC与AOP(一)

IOC AOP 一、 分层解耦 内聚&#xff1a; 软件中各个功能模块内部的功能联系 耦合&#xff1a; 衡量软件中各个层/模块之间的依赖、关联的程度 软件设计原则&#xff1a;高内聚、低耦合 ​ 控制反转&#xff1a;Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到…...

JVM运行时数据区——方法区的垃圾回收

方法区的垃圾回收主要是两部分&#xff1a;运行时常量池中废弃的常量和不在使用的类。 类卸载(将不在使用的类回收)的条件&#xff1a; 该类的所有实例均被回收。 加载该类的类加载器被回收(一般很难满足)。 类对象不再引用&#xff0c;通过反射也获取不到。...

LeetCode213.House-Robber-II<打家劫舍II>

题目&#xff1a; 思路&#xff1a; 在版本一中增加了一个条件 那就是首尾相关联。那么只需要进行两次循环即可。 第一次是循环是偷第一家的 那么循环到n-1 截至 并且保存一个cmp 第二次循环是不偷第一家的 循环到n截至。然后比较cmp 与 dp [n] 的最大值即可。 代码是&#…...

订单系统问题汇总

1、项目启动失败 原因是pom中既配置了mybatis又配置了mybatis-plus 2、idea连接后提示缺少MySQL驱动&#xff0c;直接根据提示安装就好 3、解析请求得到的json为对象时候报错&#xff0c;待解析的对象是泛型对象 String regionsInfo OkHttpRequestUtils.sendGetRequest(new…...

springboot热加载spring-boot-devtools:

springboot热加载 基于idea开发springboot项目使用热加载 pom依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</op…...

QT学习之旅 - 一个QT的基本项目

文章目录 定时器(时间)位置信息QTableWidget用cellwidget添加控件隐藏QTableWidget的滚动条自动调整适应大小 UDPUDP ClientUDP ServerUDP udpSocket.readDatagram重要参数使用多线程udp 自定义信号和槽UDP服务端接收数据(全局变量) QWT设置标题数轴相关设置坐标轴范围设置坐标…...

大数据课程D2——hadoop的概述

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解hadoop的定义和特点&#xff1b; ⚪ 掌握hadoop的基础结构&#xff1b; ⚪ 掌握hadoop的常见命令&#xff1b; ⚪ 了解hadoop的执行流程&#xff1b; 一、简介 1…...

使用nginx和ffmpeg搭建HTTP FLV流媒体服务器(摄像头RTSP视频流->RTMP->http-flv)

名词解释 RTSP &#xff08;Real-Time Streaming Protocol&#xff09; 是一种网络协议&#xff0c;用于控制实时流媒体的传输。它是一种应用层协议&#xff0c;通常用于在客户端和流媒体服务器之间建立和控制媒体流的传输。RTSP允许客户端向服务器发送请求&#xff0c;如…...

揭秘APT团体常用的秘密武器——AsyncRAT

AsyncRAT 是 2019 年 1 月在 [GitHub](https://github.com/NYAN-x-CAT/AsyncRAT-C- Sharp)上开源的远控木马&#xff0c;旨在通过远程加密链接控制失陷主机&#xff0c;提供如下典型功能&#xff1a; 截取屏幕 键盘记录 上传/下载/执行文件 持久化 禁用 Windows Defender 关机/…...

Flutter Widget Life Cycle 组件生命周期

Flutter Widget Life Cycle 组件生命周期 视频 前言 了解 widget 生命周期&#xff0c;对我们开发组件还是很重要的。 今天会把无状态、有状态组件的几个生命周期函数一起过下。 原文 https://ducafecat.com/blog/flutter-widget-life-cycle 参考 https://api.flutter.dev/f…...

LeetCode面向运气之Javascript—第2600题-K件物品的最大和-94.68%

LeetCode第2600题-K件物品的最大和 题目要求 袋子中装有一些物品&#xff0c;每个物品上都标记着数字 1 、0 或 -1 。 四个非负整数 numOnes 、numZeros 、numNegOnes 和 k 。 袋子最初包含&#xff1a; numOnes 件标记为 1 的物品。numZeroes 件标记为 0 的物品。numNegOn…...

数学建模学习(4):TOPSIS 综合评价模型及编程实战

一、数据总览 需求&#xff1a;我们需要对各个银行进行评价&#xff0c;A-G为银行的各个指标&#xff0c;下面是银行的数据&#xff1a; 二、代码逐行实现 清空代码和变量的指令 clear;clc; 层次分析法 每一行代表一个对象的指标评分 p [8,7,6,8;7,8,8,7];%每一行代表一个…...

PHP之Smarty使用以及框架display和assign原理

一、Smarty的下载 进入Smarty官网下载&#xff0c;复制目录libs目录即可http://www.smarty.net/http://www.smarty.net/ 二、使用Smarty&#xff0c;创建目录demo,把libs放进去改名为Smarty 三、引入Smarty配置,创建目录&#xff0c;index.php文件配置 <?php…...

《TCP IP网络编程》第十一章

第 11 章 进程间通信 11.1 进程间通信的基本概念 通过管道实现进程间通信&#xff1a; 进程间通信&#xff0c;意味着两个不同的进程中可以交换数据。下图是基于管道&#xff08;PIPE&#xff09;的进程间通信的模型&#xff1a; 可以看出&#xff0c;为了完成进程间通信&…...

Folx Pro 5 最好用的Mac磁力链接BT种子下载工具

除了迅雷&#xff0c;还有哪个支持磁力链接下载&#xff1f;Mac电脑如何下载磁力链接&#xff1f;经常有小伙伴问老宅。今天&#xff0c;老宅给大家推荐Folx Pro For Mac&#xff0c;Mac系统超好用的磁力下载工具。 Folx是一款功能强大且易于使用的Mac下载管理器&#xff0c;并…...

Redis 数据库的高可用

文章目录 Redis 数据库的高可用一.Redis 数据库的持久化1.Redis 高可用概念2.Redis 实现高可用的技术2.1 持久化2.2 主从复制2.3 哨兵2.4 Cluster集群 3.Redis 持久化3.1 持久化的功能3.2 Redis 提供持久化的方式3.2.1 RDB 持久化3.2.2 AOF 持久化&#xff08;append only file…...