(Head First 设计模式)学习笔记(2) --观察者模式(气象站实例)

以下内容转载请注明来自"菩提树下的杨过(http://blog.sqlsky.com)"

应用概述:
某气象站通过传感器实时测量气温/湿度/压力等数据,要求设计一个系统,能让多种类型的公告栏自动更新这些数据(本例中有二类公告板:实时显示气温/温度公告板,动态统计最高/最低气温公告板)

解释:
应用观察者模式,把气温数据做为一个主题(也称为可观察者),让其它公告板当做观察者,通过订阅主题(也称通过观察"可观察者")来得知最新的信息(当然,观察者们也可以方便的退订,从而停止自动更新)

又一设计原则:
为了交互对象之间的松耦合设计而努力。


观察者接口
Code
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5
 6namespace WeatherForecast
 7{
 8    /**//// 
 9    /// 观察者接口
10    /// 

11    public interface Observer
12    {
13        void Update(float temperature,float humidity,float pressure);//用来更新各类公告板数据 
14    }

15}

公告板显示接口
Code
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5
 6namespace WeatherForecast
 7{
 8    /**//// 
 9    /// 公告板"显示"功能接口
10    /// 

11    interface DisplayElement
12    {
13        void Display();
14        
15    }

16}

主题接口
Code
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5
 6namespace WeatherForecast
 7{
 8    /**//// 
 9    /// "主题"(也称为"被观察者")接口
10    /// 

11    public interface Subject
12    {
13        void RegisterObserver(Observer o);
14        void RemoveObserver(Observer o);
15        void NotifyObservers();
16
17    }

18}

真正的气象数据"主题"
Code
 1using System;
 2using System.Collections.Generic;
 3using System.Collections;
 4using System.Linq;
 5using System.Text;
 6
 7namespace WeatherForecast
 8{
 9    /**//// 
10    /// 实现"主题"接口的气象数据类
11    /// 

12    public class WeatherData:Subject
13    {
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        /**//// 
25        /// 注册观察者
26        /// 

27        /// 

28        public void RegisterObserver(Observer o) 
29        {
30            observers.Add(o);
31        }

32
33        /**//// 
34        /// 取消观察者
35        /// 

36        /// 

37        public void RemoveObserver(Observer o) 
38        {
39            if (observers.Contains(o))
40            {
41                observers.Remove(o);
42            }

43        }

44
45        /**//// 
46        /// 通知所有观察者
47        /// 

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        /**//// 
57        /// 当数据变化时,该方法自动被调用(实际应用中由硬件自动控制)
58        /// 

59        public void MeasurementsChanged() 
60        {
61            NotifyObservers();
62        }

63
64        /**//// 
65        /// 设置气温/温度/压力(实际应用中,这些由数据探测器自动采集并自动设置)
66        /// 

67        /// 
68        /// 
69        /// 

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

观察者之"实时气温/湿度公告板"
Code
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5
 6namespace WeatherForecast
 7{
 8    /**//// 
 9    /// 实时气温/湿度公告板
10    /// 

11    public class CurrentConditionDisplay:Observer,DisplayElement
12    {
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

观察者之"动态统计最高/最低气温公告板"
Code
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5
 6namespace WeatherForecast
 7{
 8    /**//// 
 9    /// 动态统计最高/最低气温公告板
10    /// 

11    public class StatisticDisplay:Observer,DisplayElement
12    {
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}


最终测试:
Code
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5
 6namespace WeatherForecast
 7{
 8    class Program
 9    {
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(231520);
18            weatherData.SetMeasurements(281225);
19            weatherData.SetMeasurements(301423);
20            weatherData.SetMeasurements(252035);
21
22            weatherData.RemoveObserver(statisticDisplay);//取消"statisticDisplay"的主题订阅
23
24            weatherData.SetMeasurements(182233);
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%

你可能感兴趣的:((Head First 设计模式)学习笔记(2) --观察者模式(气象站实例))