设计模式之二:观察者模式

假定我们需要为Weather-O-Rama公司建立一个气象站系统,除已有的WeatherData有数据源类,还需要更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报。

 1 以下是一个可能的实现

class WeatherData
{
private://实例变量声明public:void measurementsChanged(){float temp = getTemperature();float humidity = getHumidity();float pressure = getPressure();currentConditionsDisplay.update(temp, humidity, pressure);statisticsDisplay.update(temp, humidity, pressure);forecastDisplay.update(temp, humidity, pressure);}float getTemperature() {}float getHumidity() {}float getPressure() {}
};

上述实现有以下问题存在:

  • 针对具体实现编程,而非针对接口(currentConditionsDisplay都是具体的实例)
  • 针对每个新的布告板,都得修改代码(添加新的布告板到代码中)
  • 无法在运行时动态增删布告板
  • 尚未封装改变的部分(调用几个update的地方)

2 观察者模式

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

主题是具有状态的对象,并且可以控制这些状态。另一方面,观察者使用这些状态,虽然这些状态不属于他们。

观察者模式提供了一种对象设计(设计原则:为了交互对象之间的松耦合设计而努力),让主题和观察者之间松耦合。

主题只知道观察者实现了某个接口,并不需要知道具体的观察者是谁,做了什么动作。同时,我们也可以在运行时增删观察者。

class Subject
{
public:virtual void registerObserver(Observer o) = 0;virtual void removeObserver(Observer o) = 0;virtual void notifyObserver() = 0;
};class Observer
{
public:virtual void update(float temp, float humidity, float pressure) = 0;
};class DisplayElement
{
public:virtual void display() = 0;
};

// WeatherData实现接口class WeatherData : public Subject
{
private:std::vector<Observer*> observers;float temprature;float humidity;float pressure;public:WeatherData(){observers = new vector<Observer*>();}void registerObserver(Observer* o){observers.add(o);}void removeObserver(Observer* o){observers.remove(o);}void notifyObserver(){for (Observer* o : observers){o->update(temprature, humidity, pressure);}}void measurementsChanged(){notifyObserver();}
};
// 布告板实现Observer接口// 为什么要保存对Subject的引用呢,构造完后好像并未使用?
// 以后可能想要取消注册,如果有对Subject的引用会比较方便。class CurrentConditionsDisplay : public Observer, DisplayElement
{
private:Subject* weatherData;float temprature;float humidity;public:CurrentConditionsDisplay(Subject* weatherData){this->weatherData = weatherData;weatherData->registerObserver(this);}void update(float temp, float humidity, float pressure){this->temprature = temp;this->humidity = humidity;display();}void display(){std::cout << "Temprature:" << temprature << "Humidity:" << humidity << std::endl;}
};

除使用上面的“推”方式主动将数据传送给观察者,还可以通过“拉”方式主动拉取数据(可以传递一个主题对象,或者数据对象给update方法,或者从私有变量中提取)。

// 主题本身作为变量,可以让观察者知道是哪个主题通知的
update(Observer o) {}// Java的内置实现有setChanged()方法,可以在更新观察者时具有更多的弹性,比如什么时候可以
// 不更新,什么时候更新

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++类相关概念

1. 函数形参默认值 &#xff08;1&#xff09; 建议函数&#xff08;不仅仅是构造函数&#xff09;形参默认值只在函数声明中指定&#xff1b; &#xff08;函数声明和定义写在同一个文件中&#xff0c;则函数声明、定义两者之一或两者都可指定形参默认值&#xff0c;两者都指…

云原生监控——VictoriaMetrics

1.简介 VictoriaMetrics是一个快速高效且可扩展的监控解决方案和时序数据库&#xff0c;可以作为Prometheus的长期远端存储&#xff0c;具备的特性有&#xff1a; 支持prometheus查询api&#xff0c;同时实现了一个metricsql 查询语言支持全局查询视图&#xff0c;支持多prom…

在OK3588的Ubuntu系统上安装Firefox浏览器

文章目录 概要配置上网环境安装的具体命令 概要 因为Ubuntu系统里面没有安装浏览器&#xff0c;为了方便使用&#xff0c;提高工作效率&#xff0c;我们安装一下Firefox浏览器。 Firefox是一款适用于Ubuntu系统的免费和开源的Web浏览器。由Mozilla Foundation和其子公司Mozil…

生成图片验证码-Google Kaptcha

CaptchaImage生成 验证码 图片 captchaProducerMath.createText() 类似 captchaProducer.createText() 混合带字符的char如下 从若依学的&#xff0c;先看他的引用方式 package com.ruoyi.web.controller.common;import java.awt.image.BufferedImage; import java.io.IOExcept…

【数据仓库】BI看板DataEase入坑指南

开头夸夸国产开源BI软件DataEase&#xff0c;支持常见各种报表&#xff0c;还支持图表联动和上下级钻取&#xff0c;超赞有木有&#xff01;&#xff01;&#xff01; 再来为什么说入坑&#xff0c;源码启动各种不服啊。本地用的maven3.5一直导入不了Java项目backend。后来看了…

React-Native学习,RN的容器Flex-Box布局

justify-content&#xff08;在RN中属性名称为&#xff1a;justifyContent&#xff09;在主轴上对齐方式 align-items&#xff08;在RN中属性名称为&#xff1a;alignItems&#xff09;在交叉轴上的对齐方式 在React Native中&#xff0c;当没有设置容器的主轴方向时&#xf…

觉非科技李东旻:智能驾驶向大模型的进化与感知决策新范式的诞生

由亿欧汽车主办“AI与新一代车载智能感知融合创新论坛”近日登陆2023世界人工智能大会&#xff08;WAIC&#xff09;。觉非科技CEO李东旻受邀发表了“智能驾驶向大模型的进化与感知决策新范式的诞生”主题演讲&#xff0c;从产业趋势结合技术发展特点以及在感知决策中的能力应用…

【安卓12源码】WMS的作用及其启动流程

一、WMS 的作用 WMS 在 Android 系统的地位&#xff0c;它作为中间层&#xff0c;连接了上层的 View 框架和下层的 SurfaceFingler。 WMS 主要职责 窗口管理&#xff1a;负责启动、添加、删除窗口&#xff0c;管理窗口大小、层级&#xff0c;核心成员有&#xff1a;WindowCont…

Java的Hibernate框架中集合类数据结构的映射编写教程

Java的Hibernate框架中集合类数据结构的映射编写教程 一、集合映射 1.集合小介 集合映射也是基本的映射&#xff0c;但在开发过程中不会经常用到&#xff0c;所以不需要深刻了解&#xff0c;只需要理解基本的使用方法即可&#xff0c;等在开发过程中遇到了这种问题时能够查询…

elementui自定义loading图标

效果图如下&#xff1a; 一、在assets下新建一个mycss.css文件夹&#xff08;图片大小以及文字样式&#xff0c;可以根据自己的需求进行微调&#xff09; .el-loading-spinner {/*这个是自己想设置的 gif 加载动图*/background-image: url(../gif2.gif); background-repeat: n…

redis的分布式事务-redisson

一 redisson 1.1 redisson分布式事务 Redisson分布式锁是一种基于redis实现的分布式锁&#xff0c;它利用redis的setnx命令实现分布式锁的互斥访问。同时还支持锁的自动续期功能&#xff0c;可以避免因为某个进程崩溃或者网络故障导致锁无法释放的情况。 只要线程一加锁成功…

各种好看的css效果收集

CSS动画特效-多种方案实现CSS光束扫过&#xff0c;扫光特效&#xff0c;ae文字过光效果&#xff0c;光效移动效果 一个集合180种免费的线性渐变网站&#xff0c;可在任何网站使用您不仅可以复制渐变的原生CSS颜色代码&#xff0c;还可以查看下载每个优质的渐变图片。 链接&…