(Head First 设计模式)学习笔记(2) --观察者模式(气象站实例)
以下内容转载请注明来自"菩提树下的杨过(http://blog.sqlsky.com)"
应用概述:
某气象站通过传感器实时测量气温/湿度/压力等数据,要求设计一个系统,能让多种类型的公告栏自动更新这些数据(本例中有二类公告板:实时显示气温/温度公告板,动态统计最高/最低气温公告板)
解释:
应用观察者模式,把气温数据做为一个主题(也称为可观察者),让其它公告板当做观察者,通过订阅主题(也称通过观察"可观察者")来得知最新的信息(当然,观察者们也可以方便的退订,从而停止自动更新)
又一设计原则:
为了交互对象之间的松耦合设计而努力。
观察者接口
1
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Text;5

6
namespace WeatherForecast7


{8

/**//// <summary>9
/// 观察者接口10
/// </summary>11
public interface Observer12

{13
void Update(float temperature,float humidity,float pressure);//用来更新各类公告板数据 14
}15
}公告板显示接口
1
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Text;5

6
namespace WeatherForecast7


{8

/**//// <summary>9
/// 公告板"显示"功能接口10
/// </summary>11
interface DisplayElement12

{13
void Display();14
15
}16
}主题接口
1
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Text;5

6
namespace WeatherForecast7


{8

/**//// <summary>9
/// "主题"(也称为"被观察者")接口10
/// </summary>11
public interface Subject12

{13
void RegisterObserver(Observer o);14
void RemoveObserver(Observer o);15
void NotifyObservers();16

17
}18
}真正的气象数据"主题"
1
using System;2
using System.Collections.Generic;3
using System.Collections;4
using System.Linq;5
using System.Text;6

7
namespace WeatherForecast8


{9

/**//// <summary>10
/// 实现"主题"接口的气象数据类11
/// </summary>12
public class WeatherData:Subject13

{14
private ArrayList observers;//订阅本主题的观察者列表15
private float temperature;16
private float humidity;17
private float pressure;18

19
public WeatherData() 20

{21
observers = new ArrayList();22
}23

24

/**//// <summary>25
/// 注册观察者26
/// </summary>27
/// <param name="o"></param>28
public void RegisterObserver(Observer o) 29

{30
observers.Add(o);31
}32

33

/**//// <summary>34
/// 取消观察者35
/// </summary>36
/// <param name="o"></param>37
public void RemoveObserver(Observer o) 38

{39
if (observers.Contains(o))40

{41
observers.Remove(o);42
}43
}44

45

/**//// <summary>46
/// 通知所有观察者47
/// </summary>48
public void NotifyObservers() 49

{50
for (int i = 0; i < observers.Count; i++)51

{52
(observers[i] as Observer).Update(temperature, humidity, pressure);53
}54
}55

56

/**//// <summary>57
/// 当数据变化时,该方法自动被调用(实际应用中由硬件自动控制)58
/// </summary>59
public void MeasurementsChanged() 60

{61
NotifyObservers();62
}63

64

/**//// <summary>65
/// 设置气温/温度/压力(实际应用中,这些由数据探测器自动采集并自动设置)66
/// </summary>67
/// <param name="temperature"></param>68
/// <param name="humidity"></param>69
/// <param name="pressure"></param>70
public void SetMeasurements(float temperature, float humidity, float pressure) 71

{72
this.temperature = temperature;73
this.humidity = humidity;74
this.pressure = pressure;75
MeasurementsChanged();//因为测试环境中,没有硬件环境,只能手动模拟调用76
}77
}78
}79

观察者之"实时气温/湿度公告板"
1
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Text;5

6
namespace WeatherForecast7


{8

/**//// <summary>9
/// 实时气温/湿度公告板10
/// </summary>11
public class CurrentConditionDisplay:Observer,DisplayElement12

{13
private float temperature;14
private float humidity;15
private Subject weatherData;16

17
public CurrentConditionDisplay(Subject weatherData) 18

{19
this.weatherData = weatherData;20
weatherData.RegisterObserver(this);21
}22

23
public void Update(float temperature, float humidity, float pressure) 24

{25
this.temperature = temperature;26
this.humidity = humidity;27
Display();28
}29

30
public void Display() 31

{32
Console.WriteLine("当前:气温" + temperature + "度,湿度" + humidity + "%");33
}34
}35
}36

观察者之"动态统计最高/最低气温公告板"
1
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Text;5

6
namespace WeatherForecast7


{8

/**//// <summary>9
/// 动态统计最高/最低气温公告板10
/// </summary>11
public class StatisticDisplay:Observer,DisplayElement12

{13
private float temperature;14
private float humidity;15
private float maxTemperature;16
private float minTemperature;17
private Subject weatherData;18

19
public StatisticDisplay(Subject weatherData) 20

{21
this.weatherData = weatherData;22
weatherData.RegisterObserver(this);23
//将下列变量初始化一个不可能达到的值24
temperature = -99999;25
maxTemperature = -99999;26
minTemperature = 99999;27
}28

29
public void Update(float temperature, float humidity, float pressure) 30

{31
this.temperature = temperature;32
this.humidity = humidity;33
34

if (maxTemperature == -99999)
{ maxTemperature = temperature; }35

if (minTemperature == 99999)
{ minTemperature = temperature; } 36

37
maxTemperature = maxTemperature > temperature ? maxTemperature : temperature;38
minTemperature = minTemperature > temperature ? temperature : minTemperature;39

40
Display();41
}42

43
public void Display() 44

{45
Console.WriteLine("统计:最高气温 " + maxTemperature + "度 ,最低气温 " + minTemperature + "度\n");46
}47

48
}49
}最终测试:
1
using System;2
using System.Collections.Generic;3
using System.Linq;4
using System.Text;5

6
namespace WeatherForecast7


{8
class Program9

{10
static void Main(string[] args)11

{12
WeatherData weatherData = new WeatherData();13

14
CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData);15
StatisticDisplay statisticDisplay = new StatisticDisplay(weatherData);16

17
weatherData.SetMeasurements(23, 15, 20);18
weatherData.SetMeasurements(28, 12, 25);19
weatherData.SetMeasurements(30, 14, 23);20
weatherData.SetMeasurements(25, 20, 35);21

22
weatherData.RemoveObserver(statisticDisplay);//取消"statisticDisplay"的主题订阅23

24
weatherData.SetMeasurements(18, 22, 33);25

26
Console.Read();27

28
}29
}30
}运行结果:
当前:气温23度,湿度15%
统计:最高气温 23度 ,最低气温 23度
当前:气温28度,湿度12%
统计:最高气温 28度 ,最低气温 23度
当前:气温30度,湿度14%
统计:最高气温 30度 ,最低气温 23度
当前:气温25度,湿度20%
统计:最高气温 30度 ,最低气温 23度
当前:气温18度,湿度22%
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
浙公网安备 33010602011771号