[读书笔记]观察者模式

概述

在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。[GOF 《设计模式》]

此系统中的三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)。WeatherData对象知道如何跟物理气象站联系,以取得更新的数据。WeatherData对象会随即更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报。

weather.png

设计如下:
uml.JPG

实现代码:

接口定义

C# Code
  1. public interface ISubject  
  2.     {  
  3.         void RegisterObserver(IObserver o);  
  4.         void RemoveObserver(IObserver o);  
  5.         void NotifyObservers();  
  6.     }  
  7.   
  8.     public interface IObserver  
  9.     {  
  10.         void Update(float temp, float humidity, float pressure);  
  11.     }  
  12.   
  13.     public interface IDisplayElement  
  14.     {  
  15.         void Display();  
  16.     }  

WeatherData类的实现

C# Code
  1. public class WeatherData : ISubject  
  2.     {  
  3.         private List<IObserver> observers;  
  4.         private float temperature;  
  5.         private float humidity;  
  6.         private float pressure;  
  7.   
  8.         public WeatherData()  
  9.         {  
  10.             if (observers == null)  
  11.                 observers = new List<IObserver>();  
  12.         }  
  13.   
  14.         public void RegisterObserver(IObserver o)  
  15.         {  
  16.             observers.Add(o);  
  17.         }  
  18.   
  19.         public void RemoveObserver(IObserver o)  
  20.         {  
  21.             observers.Remove(o);  
  22.         }  
  23.   
  24.         public void NotifyObservers()  
  25.         {  
  26.             foreach (IObserver o in observers)  
  27.             {  
  28.                 o.Update(temperature, humidity, pressure);  
  29.             }  
  30.         }  
  31.   
  32.         public void MeasureChanged()  
  33.         {  
  34.             NotifyObservers();  
  35.         }  
  36.   
  37.         public void SetMeasurements(float temperature,   
  38.                         float humidity, float pressure)  
  39.         {  
  40.             this.temperature = temperature;  
  41.            this. humidity = humidity;  
  42.             this.pressure = pressure;  
  43.             MeasureChanged();  
  44.         }  
  45.     }  

CurrentConditionsDisplay类的实现:

C# Code
  1. public class CurrentConditionsDisplay : IObserver, IDisplayElement  
  2.     {  
  3.         private float temperature;  
  4.         private float humidity;  
  5.         private ISubject weatherData;  
  6.   
  7.         public CurrentConditionsDisplay(ISubject weatherData)  
  8.         {  
  9.             this.weatherData = weatherData;  
  10.             weatherData.RegisterObserver(this);  
  11.         }  
  12.   
  13.         public void Update(float temperature, float humidity,   
  14.                                 float pressure)  
  15.         {  
  16.             this.temperature = temperature;  
  17.             this.humidity = humidity;  
  18.             Display();  
  19.         }  
  20.   
  21.         public void Display()  
  22.         {  
  23.             Console.WriteLine("Current Condition: "  
  24.                         + temperature + " F degrees and "  
  25.                         + humidity + " % humidity");  
  26.         }  
  27.     }  

测试代码:

C# Code
  1. static void Main(string[] args)  
  2. {  
  3.     WeatherData weatherData = new WeatherData();  
  4.     CurrentConditionsDisplay currentConditionDisplay  
  5.         = new CurrentConditionsDisplay(weatherData);  
  6.   
  7.     weatherData.SetMeasurements(80, 65, 30.4f);  
  8.     weatherData.SetMeasurements(82, 70, 29.2f);  
  9.     weatherData.SetMeasurements(78, 90, 29.2f);  
  10.   
  11.     Console.ReadLine();  
  12. }  

运行结果:
result.jpg

.Net Solution (VS2008) 在这里

1 comment so far

  1. 21sta March 22, 2008 12:33 am

    你的blog可是消失了好长一段时间。欢迎归来

Leave a comment

Please be polite and on topic. Your e-mail will never be published.