Observer 观察者模式

Posted blackteeth

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Observer 观察者模式相关的知识,希望对你有一定的参考价值。

项目:气象监测系统

需求分析::此系统中三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)。

WeatherData对象知道如何跟物理气象站联系,以取得更新的数据。WeatherData对象会随机更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报。

当WeatherData对象发生变化时,即刻更新数据并推送给三个布告板。因此WeatherData需要获得布告板的引用,在数据更新时发送给布告板。用代码说话:

首先设计2个接口:

1. Subject,包含3个方法:Register, Remove, NotifyObservers

2.Observer, 包含1个方法:Update

设计WeatherData,实现Subject。除此之外还需要获得布告板引用,添加字段observerList集合,以及温度、湿度、气压字段。还有设置天气属性的的方法SetMeasurements,

MeasurementsChanged方法,当设置天气属性时即调用改方法,然后通知注册的用户。

1 namespace ObserverPattern
2 {
3     public  interface Subject
4     {
5         void RegisterObserver(Observer o);
6         void RemoveObserver(Observer o);
7         void NotifyObservers();
8     }
9 }
1 namespace ObserverPattern
2 {
3     public interface Observer
4     {
5         void Update(float temp, float humidity, float pressure);
6     }
7 }
 1 using System.Collections.Generic;
 2 
 3 namespace ObserverPattern
 4 {
 5     public class WeatherData : Subject
 6     {
 7         private List<Observer> observerList = new List<Observer>();
 8         private float temperature;
 9         private float humidity;
10         private float pressure;
11 
12         public void NotifyObservers()
13         {
14             foreach (Observer o in observerList)
15             {
16                 o.Update(temperature, humidity, pressure);
17             }
18         }
19 
20         public void RegisterObserver(Observer o)
21         {
22             observerList.Add(o);
23         }
24 
25         public void RemoveObserver(Observer o)
26         {
27             if(observerList.Contains(o))
28             {
29                 observerList.Remove(o);
30             }
31           
32         }
33         /// <summary>
34         /// 设置温度、湿度、气压
35         /// </summary>
36         /// <param name="temperature">温度</param>
37         /// <param name="humidity">湿度</param>
38         /// <param name="pressure">气压</param>
39         public void SetMeasurements(float temperature, float humidity, float pressure)
40         {
41             this.temperature = temperature;
42             this.humidity = humidity;
43             this.pressure = pressure;
44             MeasurementsChanged();
45         }
46         private void MeasurementsChanged( )
47         {
48             NotifyObservers();
49         }
50     }
51 }

接下来时设计3个布告板类,直接上代码:

 1 using System;
 2 
 3 namespace ObserverPattern
 4 {
 5     /// <summary>
 6     /// 此布告板根据WeatherData对象显示当前观测值
 7     /// </summary>
 8     public class CurrentConditionsDisplay : Observer, DisplayElement
 9     {
10         private float temperature;
11         private float humidity;
12       
13         private Subject weatherData;
14 
15         public CurrentConditionsDisplay()
16         {
17 
18         }
19         public CurrentConditionsDisplay(Subject w)
20         {
21             weatherData = w;
22             weatherData.RegisterObserver(this);
23         }
24         /// <summary>
25         /// 把最近的温度和湿度显示出来
26         /// </summary>
27         public void Display()
28         {
29             Console.WriteLine("Current conditions:{0} F degress and {1} % humidity", temperature, humidity);
30         }
31 
32      
33         public void Update(float temp, float humidity, float pressure)
34         {
35             this.temperature = temp;
36             this.humidity = humidity;
37             Display();
38         }
39     }
40 }
 1 using System;
 2 
 3 namespace ObserverPattern
 4 {
 5     /// <summary>
 6     /// 此布告板根据气压计显示天气预报
 7     /// </summary>
 8     public class ForecastDisplay : Observer, DisplayElement
 9     {
10         private WeatherData weatherData;
11         private float currentPressure = 29.92f;
12         private float lastPressure;
13         public ForecastDisplay()
14         {
15 
16         }
17         public ForecastDisplay(WeatherData w)
18         {
19             weatherData = w;
20             w.RegisterObserver(this);
21         }
22         public void Display()
23         {
24             Console.Write("Forecast: ");
25             if(currentPressure > lastPressure)
26             {
27                 Console.WriteLine("天气状况转良!");
28             }
29             else if(currentPressure == lastPressure)
30             {
31                 Console.WriteLine("气压没有变化");
32             }
33             else
34             {
35                 Console.WriteLine("注意天气变凉,雨水天气");
36             }
37         }
38 
39       
40 
41         public void Update(float temp, float humidity, float pressure)
42         {
43             lastPressure = currentPressure;
44             currentPressure = pressure;
45             Display();
46         }
47     }
48 }
 1 using System;
 2 
 3 namespace ObserverPattern
 4 {
 5     /// <summary>
 6     /// 此布告板跟踪最小、平均、最大的观测值,并显示它们
 7     /// </summary>
 8     public class StatisticsDisplay : Observer, DisplayElement
 9     {
10         private WeatherData weatherData;
11         private float maxTemp = 0f;
12         private float minTemp = 200f;
13         private float tempSum = 0f;
14         private static int numReadings = 0;
15         public StatisticsDisplay(WeatherData w)
16         {
17             weatherData = w;
18             weatherData.RegisterObserver(this);
19         }
20         public StatisticsDisplay()
21         {
22                 
23         }
24         public void Display()
25         {
26             Console.WriteLine("Avg/Max/Min temperature = " + (tempSum / numReadings)
27             + "/" + maxTemp + "/" + minTemp);
28         }
29 
30        
31 
32         public void Update(float temp, float humidity, float pressure)
33         {
34             tempSum += temp;
35             numReadings++;
36             if(temp > maxTemp)
37             {
38                 maxTemp = temp;
39             }
40             if(temp < minTemp)
41             {
42                 minTemp = temp;
43             }
44             Display();
45         }
46     }
47 }

                                     

 1 using System;
 2 
 3 namespace ObserverPattern
 4 {
 5     class WeatherStation
 6     {
 7         static void Main(string[] args)
 8         {
 9             WeatherData weatherData = new WeatherData();
10             CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
11             ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
12             StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
13             //模拟气象测量
14             weatherData.SetMeasurements(80f, 65f, 30.4f);
15             weatherData.SetMeasurements(100f, 62f, 28.0f);
16             weatherData.SetMeasurements(86f, 72f, 26.3f);
17             Console.ReadKey();
18         }
19     }
20 }

运行结果:

技术分享图片

 

以上是关于Observer 观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

观察者模式(Observer Pattern)

[Android&amp;Java]浅谈设计模式-代码篇:观察者模式Observer

JAVA观察者模式(observer pattern)

JDK自带的Observable和Observer实现观察者模式

设计模式之- 观察者模式(Observer Pattern)

行为类模式:观察者(Observer)