首页 > 其他 > 详细

10分钟一个设计模式系列-The Observer Pattern

时间:2014-03-30 12:35:55      阅读:479      评论:0      收藏:0      [点我收藏+]

10分钟一个设计模式系列

The Observer Pattern

1. 基础 Basic

    Observer Pattern,说穿了,类似于手机应用里面的“发布-订阅”的形式,有一个Subject接口提供内容的获取,更新,并且Subject需要注册(register)很多个Observer观察者,而具有显示数据功能Display的类将继承Observer接口作为观察者,只有当你在Subject里注册了这个Observer时,Subject一有数据更新就会通知(notify)所有注册的Observers去更新(update)内容。

现在我们来看看一个UML图,摘自《Head First Design Patterns》。

bubuko.com,布布扣

在这里面,我们可以看到有Subject接口和Observer接口,分别有两个ConcreteXX的具体实现接口功能的类。这就是Observer模式的基本概念。

 

2. 例子 Example

    我们来看一个具体的例子,有一个气象台WeatherStation负责获取天气的数据,天气气象台的类有3个getter,分别获取气温,湿度,气压,getTemperature(),getHumidity(),getPressure()。有很多个设备负责显示这些数据,那么应该如何实现这个例子?

 

3. Java内置API实现 Java Built in Support API - Observable Class & Observer Interface

    其实,Java也有内置帮助实现Observer模式的功能,是java.util包里面的Observable类以及Observer接口。请注意,Observable是一个类,而Observer是一个接口,这两点很重要,稍后会详细解释。我们先看看Observable类。

bubuko.com,布布扣

其实,它就是一个类似的Subject接口的类,但这里面有一个setChanged()方法。当你的Subject数据更新时,你需要先setChanged(),再notifyObservers(),为什么会多出来这个setChanged()方法?暂且不表,我们先看一下notifyObservers()在java里是如何实现的。

bubuko.com,布布扣
 1 public void notifyObservers(Object arg) {
 2    Object[] arrLocal;
 3    synchronized (this) {
 4       if (!changed)
 5                  return;
 6       arrLocal = obs.toArray();
 7       clearChanged();
 8    }
 9    for (int i = arrLocal.length-1; i>=0; i--)
10        ((Observer)arrLocal[i]).update(this, arg);
11 }
bubuko.com,布布扣

从这段代码可以看到,它会有一个先判定boolean changed是否改变的过程。然后再一一调用Observer数组中的Observer.update()去更新各个Observer的内容。

那刚才的问题就可以解答了,为什么会多出来这个setChanged()方法?这个方法的好处是,你的subject不一定每时每刻都要去告诉observer观察者去更新内容,只有当想通知时,再通知。这就是好处了,但值得注意的是,如果去看java的源代码,setChanged()是protected,这也就会引起直接用java提供的类和接口实现这个模式会出现的一些不方便的地方。

Java中的Observer是一个接口,也是一个update()方法,所以没什么好说的。

4. Java Observable类的限制 Limitation of the Java Observable Class

    刚才说过,java中Observable是一个类,而且类中的setChanged()是一个protected方法。这就带来了一个问题,因为它是一个类,那么你只能作为一个子类subclass去继承它,但假如我们这个类需要继承别的具体的类呢,或许有人会说new一个Observable实例出来,但这里又有一个问题,它是setChanged()是protected方法,那么new出来的这个实例是无法调用setChanged()方法的,无法调用它,就没办法notifyObservers()。这里提供两种方法来解决这个问题:

1. 照旧继承你原来继承的另外的类,然后直接在这个子类里面重新实现Observable类的内容,或者重新写一个Subject接口,添加Observable的方法。

2. 继承Observable,然后在subclass里面创建一个你原本想继承的那个类的实例作为一个“中介”,去实现具体的其它功能。

10分钟一个设计模式系列-The Observer Pattern,布布扣,bubuko.com

10分钟一个设计模式系列-The Observer Pattern

原文:http://www.cnblogs.com/Jam01/p/3633566.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!