(Head First 设计模式)学习笔记(2) --观察者模式(气象站实例)
时间:2022-04-23
本文章向大家介绍(Head First 设计模式)学习笔记(2) --观察者模式(气象站实例),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
应用概述: 某气象站通过传感器实时测量气温/湿度/压力等数据,要求设计一个系统,能让多种类型的公告栏自动更新这些数据(本例中有二类公告板:实时显示气温/温度公告板,动态统计最高/最低气温公告板)
解释: 应用观察者模式,把气温数据做为一个主题(也称为可观察者),让其它公告板当做观察者,通过订阅主题(也称通过观察"可观察者")来得知最新的信息(当然,观察者们也可以方便的退订,从而停止自动更新)
又一设计原则: 为了交互对象之间的松耦合设计而努力。
观察者接口
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeatherForecast
{
/// <summary>
/// 观察者接口
/// </summary>
public interface Observer
{
void Update(float temperature,float humidity,float pressure);//用来更新各类公告板数据
}
}
公告板显示接口
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeatherForecast
{
/// <summary>
/// 公告板"显示"功能接口
/// </summary>
interface DisplayElement
{
void Display();
}
}
主题接口
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeatherForecast
{
/// <summary>
/// "主题"(也称为"被观察者")接口
/// </summary>
public interface Subject
{
void RegisterObserver(Observer o);
void RemoveObserver(Observer o);
void NotifyObservers();
}
}
真正的气象数据"主题"
Code
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace WeatherForecast
{
/// <summary>
/// 实现"主题"接口的气象数据类
/// </summary>
public class WeatherData:Subject
{
private ArrayList observers;//订阅本主题的观察者列表
private float temperature;
private float humidity;
private float pressure;
public WeatherData()
{
observers = new ArrayList();
}
/// <summary>
/// 注册观察者
/// </summary>
/// <param name="o"></param>
public void RegisterObserver(Observer o)
{
observers.Add(o);
}
/// <summary>
/// 取消观察者
/// </summary>
/// <param name="o"></param>
public void RemoveObserver(Observer o)
{
if (observers.Contains(o))
{
observers.Remove(o);
}
}
/// <summary>
/// 通知所有观察者
/// </summary>
public void NotifyObservers()
{
for (int i = 0; i < observers.Count; i++)
{
(observers[i] as Observer).Update(temperature, humidity, pressure);
}
}
/// <summary>
/// 当数据变化时,该方法自动被调用(实际应用中由硬件自动控制)
/// </summary>
public void MeasurementsChanged()
{
NotifyObservers();
}
/// <summary>
/// 设置气温/温度/压力(实际应用中,这些由数据探测器自动采集并自动设置)
/// </summary>
/// <param name="temperature"></param>
/// <param name="humidity"></param>
/// <param name="pressure"></param>
public void SetMeasurements(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
MeasurementsChanged();//因为测试环境中,没有硬件环境,只能手动模拟调用
}
}
}
观察者之"实时气温/湿度公告板"
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeatherForecast
{
/// <summary>
/// 实时气温/湿度公告板
/// </summary>
public class CurrentConditionDisplay:Observer,DisplayElement
{
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionDisplay(Subject weatherData)
{
this.weatherData = weatherData;
weatherData.RegisterObserver(this);
}
public void Update(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
Display();
}
public void Display()
{
Console.WriteLine("当前:气温" + temperature + "度,湿度" + humidity + "%");
}
}
}
观察者之"动态统计最高/最低气温公告板"
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeatherForecast
{
/// <summary>
/// 动态统计最高/最低气温公告板
/// </summary>
public class StatisticDisplay:Observer,DisplayElement
{
private float temperature;
private float humidity;
private float maxTemperature;
private float minTemperature;
private Subject weatherData;
public StatisticDisplay(Subject weatherData)
{
this.weatherData = weatherData;
weatherData.RegisterObserver(this);
//将下列变量初始化一个不可能达到的值
temperature = -99999;
maxTemperature = -99999;
minTemperature = 99999;
}
public void Update(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
if (maxTemperature == -99999) { maxTemperature = temperature; }
if (minTemperature == 99999) { minTemperature = temperature; }
maxTemperature = maxTemperature > temperature ? maxTemperature : temperature;
minTemperature = minTemperature > temperature ? temperature : minTemperature;
Display();
}
public void Display()
{
Console.WriteLine("统计:最高气温 " + maxTemperature + "度 ,最低气温 " + minTemperature + "度n");
}
}
}
最终测试:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeatherForecast
{
class Program
{
static void Main(string[] args)
{
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData);
StatisticDisplay statisticDisplay = new StatisticDisplay(weatherData);
weatherData.SetMeasurements(23, 15, 20);
weatherData.SetMeasurements(28, 12, 25);
weatherData.SetMeasurements(30, 14, 23);
weatherData.SetMeasurements(25, 20, 35);
weatherData.RemoveObserver(statisticDisplay);//取消"statisticDisplay"的主题订阅
weatherData.SetMeasurements(18, 22, 33);
Console.Read();
}
}
}
运行结果: 当前:气温23度,湿度15% 统计:最高气温 23度 ,最低气温 23度
当前:气温28度,湿度12% 统计:最高气温 28度 ,最低气温 23度
当前:气温30度,湿度14% 统计:最高气温 30度 ,最低气温 23度
当前:气温25度,湿度20% 统计:最高气温 30度 ,最低气温 23度
当前:气温18度,湿度22%
- 自定义圆角和园边的实现
- Rafy 中的 Linq 查询支持(根据聚合子条件查询聚合父)
- 应用潜在语义分析技术将文档进行3D可视化
- 利用神经网络算法的C#手写数字识别
- fastText、TextCNN、TextRNN…这套NLP文本分类深度学习方法库供你选择
- nfc开发
- N-CryptoAsset投资组合 | 使用PCA识别高度相关的加密货币(最近听说某币很疯狂哦!)
- 仿刮刮乐刮奖效果
- Spacebuilder在Mono上运行修改备忘
- maven配置详解
- 这一新的可视化方法教你优雅地探索相关性
- LSTM Networks在股票市场上的探究
- MSBuild的简单介绍与使用
- actionbar详解(二)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- (leetcode每日打卡)秋叶收藏集【动态规划】
- 设计模式~调停者模式(Mediator)
- Sequential Nim(CodeForces - 1382B)【博弈】
- Less Coin Tosses(Gym - 102346L)【打表+找规律】
- leetcode1558题解【贪心】
- 如何将炫酷的报表直接截图发送邮件——在Superset 0.37使用Schedule Email功能
- Kafka监控必备——Kafka-Eagle 2.0.2正式发布
- 安防/教育/互联网直播视频组件EasyRTSPServer读取本地文件报错找不到EasyStreamClient.dll解决方法
- C语言编程入门之--第六章C语言控制语句
- RTSP网络摄像头网页无插件直播视频平台EasyNVR自定义标题和CopyRight步骤
- 设计模式~解释器
- RTSP/GB28181/HIKSDK/Ehome协议视频上云服务平台EasyCVR人脸识别开发ArcSoftFace环境搭建
- RTSP/GB28181/HIKSDK/EHome流媒体协议视频上云网关EasyCVR流地址密码不正确如何修正?
- tmux终端意外出现控制字符
- clickhouse编译安装以及搭建mysql实时复制