`
yan465942872
  • 浏览: 14157 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

设计模式学习之二观察者模式(Observer)——参与气象观测站的设计

 
阅读更多

业务需求:希望建立下一代Internet气象观测站!该气象站必须建立在我们专利申请中的WeatherData对象上,WeatherData对象负责追踪目前的天气状况(温度、湿度、气压)。要求:建立一个应用,有三种布告板,分别显示目前的状况,气象统计及简单的预报。当WeatherObject对象获得最新的测量数据时,三种布告板必须实时更新。而且,这是一个可以扩展的气象站,Weather-O-Rama气象站希望能有一组API,好让其他开发人员可以写出自己的气象布告板,并插入此应用中。接下来看WeatherDate类

先看一个错误的示范

我们的实现有什么不对呢,仔细想想oo的设计原则就知道了

currentConditionsDisplay.update(temp, humidity, pressure);

statisticsDisplay.update(temp, humidity, pressure);

forecastDisplay.update(temp, humidity, pressure);

这里针对了具体实现编程,会使我们在增加或删除布告板时必须修改程序,而且布告板的方法都是update,至少这里看起来应该像是一个统一的接口。改变的地方需要封装滴。。。。

那么先让我们认识一下观察者模式吧,报纸订阅的方式估计大家都能想明白,如果你明白报纸订阅是怎么回事,那么恭喜你,你已经明白观察者模式是怎么回事了。 出版者+订阅者=观察者模式,把名称改一下吧,改的专业一点,出版者改成 主题(Subject), 订阅之改成 观察者(Observer),改后 主题(Subject)+观察者(Observer)=观察者模式(Observer),那么根据报纸的订阅方式可以给观察者模式下定义了:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。稍后你会看到实现观察者模式的方法不止一种,但是以包含Subject和Observer接口的类设计的做法最常见。下面是观察者模式的类图,直接截的图:

观察者模式提供了一种对象设计,让主题和观察者之间松耦合(解耦合),我们可以独立的复用主题或观察者,因为二者并非紧耦合,只要他们之间的接口仍被遵守,我们就可以自由的改变他们。由此,我们又碰到一个设计原则:为了交互对象之间的松耦合(解耦合)设计而努力。OK 看过观察者模式了,那么开始设计气象站吧,设计图如下:

根据上面的类图,来实现气象站吧,先从建立接口开始,代码如下:

继续在WeatherData中实现主题接口

接下来建立布告板:

最后可以建立一个测试程序来看我们的劳动成果了:

到此,气象站算初步完成了。但是 Java API 有内置的观察者模式。java.util包内包含最基本的Observer接口与Observable类,这和我们的Subject接口与Observer接口很类似,Observer接口与Observable类使用起来更方便,因为许多功能都已经事先准备好了,上面我们自己实现的只是使用推(push)传送数据,但在内置的模式中可以使用推(push)或拉(pull)的方式传送数据。使用内置的观察者模式重新设计气象站:

我们再做一次气象站,但这次用拉(pull)来传送数据。首先,把WeatherDate改成使用java.util.Observable:

现在也让我们重做CurrentConditionsDisplay:

运行WeatherStation.java再次进行测试。。。。不知你注意到了吗,可观察者是一个“类”而不是一个“接口“,违反了针对接口编程,而非针对实现编程。如果你看看Observable的API,你会发现setChanged()方法被保护起来了(被定义成了protected),这意味着:除非你继承自Observable,否则无法创建Observable实例并组合到你自己的对象中来。这个设计违反了:多用组合,少用继承。但是当你熟悉观察者模式之后这一切都不是问题,你可以自己实现的,选择权在于你。其实,并非只有在java.util中才能找到观察者模式,其实在JavaBeans和Swing中,也都实现了观察者模式。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics