第二篇 观察者模式
好久没写文章了,为我的懒惰害臊一下.
首先还是需求,我们现在有个新项目,做一个气象站的项目,负责提供气象资料(temperature, humidity, pressure) 给天气显示板,这里有2个显示板,一个是状态显示板,一个统计显示板.
ok,这个很简单,我们立马开始动手做uml图
每当气象站获得新信息的时候,就开始调用UpdateDisplay方法,更新气象显示板的资料,如下代码
public class WeatherData { public IDisplay display1, display2; double _temperature; public Double Temperature { get { return _temperature; } set { _temperature = value; MessurementChanged();} } double _humidity; public Double Humidty { get { return _humidity; } set { _humidity = value; MessurementChanged();} } double _pressure; public Double Pressure { get { return _pressure; } set { _pressure = value;} } public void MessurementChanged() { UpdateDisplay(); } public void UpdateDisplay() { display1.Temperature = this.Temperature; display1.Humidty = this.Humidty; display2.Temperature = this.Temperature; display2.Humidty = this.Humidty; } }
ok,这么做工作的很好,但是,现在又新的显示板加入,怎么办呢,只好更改WeatherData类,加入新的支持,那么如果显示板更改需求,不再需要temperature温度 ,而需要pressure大气压的数值呢,还是要更改WeatherData类,这样,根本无法做到封装的目的,只能面对无穷无尽的修改和重编译.
这里我们就需要用到观察者模式了,什么是观察者模式,有句话是这么形容的: publish+subscriber=Observer Pattern,或则成为 subject(主题) +observer(观察者), 观察者模式是很重要的一个模式,我们想象下显示生活报纸订阅系统是怎么做的,用户随时订阅报纸,也可以随时退订.只要用户订阅了,那么一有新报纸,就会通知用户,并发送新资料给用户.还有在c#里我们经常用到的delegate,event之类,一开始我常感到很惊奇,这些是怎么做到的呢,其实这些就是观察者模式的一个演化.发布者状态一发生变化,订阅者就接受到消息. 发布者并不知道订阅者的具体情况,他们互相十分独立,这也是面向对象的一个重要原则:尽量使关联事物之间以松耦合链接.观察者模式图示如下.
当观察者注册的时候,主题把观察者放到一个容器里面.
当观察者退出的时候,主题把观察者从容器里面移除.
当主题状态一发生变化,主题首先从容器里面获得观察者的集合,然后把消息通知这些观察者.
观察者收到消息,就可以做自己想做的.
我们了解了观察者模式, 那么我们回到气象站项目 , 这里气象站中心就是主题,气象显示板就是观察者.我们可以画uml图如下
具体代码如下,分8个类
第一部分,主题3个类(为了方便观看,把3个文件放在一起)
//file:IObservable.cs using System; public interface IObservable { void RegisterObserver(IObserver observer); void UnRegisterObserver(IObserver observer); void NotifyObserver(); } //file:Subject.cs using System; using System.Collections.Generic; public class Subject:IObservable { private List
第二部分,观察者部分分4个类,如下
//file:IObserver.cs using System; public interface IObserver { void Update(object sender); } //file:IDisplay.cs using System; public interface IDisplay { void Display(); } //file:GeneralDisplay.cs using System; public class GeneralDisplay:IObserver,IDisplay { private double temperature,humidity; public void Update(object sender) { if (sender is WeatherData) { WeatherData wd=(WeatherData)sender; this.temperature=wd.Temperature; this.humidity=wd.Humidity; Display(); } } public void Display() { Console.WriteLine("current temperature is {0} C,humidity is{1}",temperature,humidity); } } //file:StatisticsDisplay.cs using System; using System.Collections.Generic; public class StatisticsDisplay:IObserver,IDisplay { private List
最后就是程序入口,让我们看一下具体效果了,如下
using System; public class Program { public static void Main() { WeatherData wd=new WeatherData(20,80,40); IObserver genDis=new GeneralDisplay(); IObserver staDis=new StatisticsDisplay(); wd.RegisterObserver(genDis); wd.RegisterObserver(staDis); wd.Temperature=25; wd.Temperature=30; wd.Humidity=70; Console.ReadLine(); } }
运行结果如下:
current temperature is 25 C,humidity is80
min/max/avg temperature is 25,25,25
current temperature is 30 C,humidity is80
min/max/avg temperature is 25,30,27.5
current temperature is 30 C,humidity is70
min/max/avg temperature is 25,30,28.3333333333333
总结
当事物之间存在一对多的关系,当“一”变化的时候,其他事物将自动收到消息并更新,这种模式称为观察者模式。
思考
是否感觉有点触发事件的感觉,不错,在c#里面使用delegate和event可以使以上代码更简练.我们通过使用delegate的方式修改代码,分为5个类,Idisplay,GenerealDisplay,StatisticsDisplay,WeatherData,Program.代码如下:
//file 1 IDisplay.cs using System; public interface IDisplay { void OnUpdate(object sender,EventArgs args); void Display(); } //file 2 GeneralDisplay.cs using System; public class GeneralDisplay:IDisplay { private double temperature,humidity; public void OnUpdate(object sender,EventArgs args) { if (sender is WeatherData) { WeatherData wd=(WeatherData)sender; temperature=wd.Temperature; humidity=wd.Humidity; Display(); } } public void Display() { Console.WriteLine("current temperature is {0} C,humidity is {1}",temperature,humidity); } } //file 3 StatisticsDisplay.cs using System; using System.Collections.Generic; public class StatisticsDisplay:IDisplay { private List
这里关键的地方时WeathData类添加的event,delegata,event后台工作我的理解其实就是一种Observer模式.程序运行结果同以前的代码一致,对照着看,可以更好的理解delegate,event和observer模式.
下一篇:《Head First Design Patterns》笔记三:装饰者模式(Decorator Pattern)
上一篇:《Head First Design Patterns》笔记一:策略模式(Strategy Pattern)