以下内容转载请注明来自"菩提树下的杨过(http://blog.sqlsky.com)"
应用概述:
某气象站通过传感器实时测量气温/湿度/压力等数据,要求设计一个系统,能让多种类型的公告栏自动更新这些数据(本例中有二类公告板:实时显示气温/温度公告板,动态统计最高/最低气温公告板)
解释:
应用观察者模式,把气温数据做为一个主题(也称为可观察者),让其它公告板当做观察者,通过订阅主题(也称通过观察"可观察者")来得知最新的信息(当然,观察者们也可以方便的退订,从而停止自动更新)
又一设计原则:
为了交互对象之间的松耦合设计而努力。
观察者接口
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
namespace WeatherForecast
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
9
/// 观察者接口
10
/// </summary>
11
public interface Observer
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
void Update(float temperature,float humidity,float pressure);//用来更新各类公告板数据
14
}
15
}
公告板显示接口
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
namespace WeatherForecast
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
9
/// 公告板"显示"功能接口
10
/// </summary>
11
interface DisplayElement
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
void Display();
14
15
}
16
}
主题接口
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
namespace WeatherForecast
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
9
/// "主题"(也称为"被观察者")接口
10
/// </summary>
11
public interface Subject
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
void RegisterObserver(Observer o);
14
void RemoveObserver(Observer o);
15
void NotifyObservers();
16![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
}
18
}
真正的气象数据"主题"
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Collections;
4
using System.Linq;
5
using System.Text;
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
namespace WeatherForecast
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
9![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
10
/// 实现"主题"接口的气象数据类
11
/// </summary>
12
public class WeatherData:Subject
13![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14
private ArrayList observers;//订阅本主题的观察者列表
15
private float temperature;
16
private float humidity;
17
private float pressure;
18![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
public WeatherData()
20![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
21
observers = new ArrayList();
22
}
23![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
25
/// 注册观察者
26
/// </summary>
27
/// <param name="o"></param>
28
public void RegisterObserver(Observer o)
29![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
30
observers.Add(o);
31
}
32![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
34
/// 取消观察者
35
/// </summary>
36
/// <param name="o"></param>
37
public void RemoveObserver(Observer o)
38![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
39
if (observers.Contains(o))
40![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
41
observers.Remove(o);
42
}
43
}
44![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
45![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
46
/// 通知所有观察者
47
/// </summary>
48
public void NotifyObservers()
49![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
50
for (int i = 0; i < observers.Count; i++)
51![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
52
(observers[i] as Observer).Update(temperature, humidity, pressure);
53
}
54
}
55![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
56![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
57
/// 当数据变化时,该方法自动被调用(实际应用中由硬件自动控制)
58
/// </summary>
59
public void MeasurementsChanged()
60![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
61
NotifyObservers();
62
}
63![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
64![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <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![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
72
this.temperature = temperature;
73
this.humidity = humidity;
74
this.pressure = pressure;
75
MeasurementsChanged();//因为测试环境中,没有硬件环境,只能手动模拟调用
76
}
77
}
78
}
79![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
观察者之"实时气温/湿度公告板"
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
namespace WeatherForecast
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
9
/// 实时气温/湿度公告板
10
/// </summary>
11
public class CurrentConditionDisplay:Observer,DisplayElement
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
private float temperature;
14
private float humidity;
15
private Subject weatherData;
16![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
public CurrentConditionDisplay(Subject weatherData)
18![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
19
this.weatherData = weatherData;
20
weatherData.RegisterObserver(this);
21
}
22![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
public void Update(float temperature, float humidity, float pressure)
24![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
25
this.temperature = temperature;
26
this.humidity = humidity;
27
Display();
28
}
29![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
public void Display()
31![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
32
Console.WriteLine("当前:气温" + temperature + "度,湿度" + humidity + "%");
33
}
34
}
35
}
36![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
观察者之"动态统计最高/最低气温公告板"
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
namespace WeatherForecast
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
9
/// 动态统计最高/最低气温公告板
10
/// </summary>
11
public class StatisticDisplay:Observer,DisplayElement
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
private float temperature;
14
private float humidity;
15
private float maxTemperature;
16
private float minTemperature;
17
private Subject weatherData;
18![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
public StatisticDisplay(Subject weatherData)
20![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
21
this.weatherData = weatherData;
22
weatherData.RegisterObserver(this);
23
//将下列变量初始化一个不可能达到的值
24
temperature = -99999;
25
maxTemperature = -99999;
26
minTemperature = 99999;
27
}
28![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
public void Update(float temperature, float humidity, float pressure)
30![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
31
this.temperature = temperature;
32
this.humidity = humidity;
33
34![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (maxTemperature == -99999)
{ maxTemperature = temperature; }
35![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (minTemperature == 99999)
{ minTemperature = temperature; }
36![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
maxTemperature = maxTemperature > temperature ? maxTemperature : temperature;
38
minTemperature = minTemperature > temperature ? temperature : minTemperature;
39![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
Display();
41
}
42![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
public void Display()
44![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
45
Console.WriteLine("统计:最高气温 " + maxTemperature + "度 ,最低气温 " + minTemperature + "度\n");
46
}
47![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
}
49
}
最终测试:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
namespace WeatherForecast
7![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
8
class Program
9![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
10
static void Main(string[] args)
11![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
12
WeatherData weatherData = new WeatherData();
13![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(weatherData);
15
StatisticDisplay statisticDisplay = new StatisticDisplay(weatherData);
16![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
weatherData.RemoveObserver(statisticDisplay);//取消"statisticDisplay"的主题订阅
23![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
weatherData.SetMeasurements(18, 22, 33);
25![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
Console.Read();
27![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
}
29
}
30
}
运行结果:
当前:气温23度,湿度15%
统计:最高气温 23度 ,最低气温 23度
当前:气温28度,湿度12%
统计:最高气温 28度 ,最低气温 23度
当前:气温30度,湿度14%
统计:最高气温 30度 ,最低气温 23度
当前:气温25度,湿度20%
统计:最高气温 30度 ,最低气温 23度
当前:气温18度,湿度22%