观察者模式又被称为依赖(Dependents)或发布-订阅模式(Publish-Subscribe).
意图: 定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新.
问题: 当某个事件发生时,你需要相一系列对象发出通知, 而这个对象的列表是变化的.
实现:
- 让"希望知道某个事件何时发生"的对象(Observer)将自己注册到另一个"监视时间发生或自己触发事件"的对象(Subject)上.
- 当事件发生时, Subject 告诉 Observer "你关心的事件已经发生了"
- 为了能让所有的观察者型对象实现Observer接口,有时候需要使用Adapter模式.
示意图:
示例:
在Java包中容纳了Oberver模式的一个实现版本.Observable类和Observer接口组成了这个模式. Observable类扮演了Subject的角色,是被观察者, Observer是观察者的超类.
主题(被观察者):
java 代码
- public class Observable {
- private boolean changed = false;
- //保存所有观察者
- private Vector obs;
- public Observable() {
- obs = new Vector();
- }
- //注册一个观察者
- public synchronized void addObserver(Observer o) {
- if (o == null)
- throw new NullPointerException();
- if (!obs.contains(o)) {
- obs.addElement(o);
- }
- }
- //移除一个观察者
- public synchronized void deleteObserver(Observer o) {
- obs.removeElement(o);
- }
- //如果状态改变通知所有观察者
- public void notifyObservers() {
- notifyObservers(null);
- }
- //如果状态改变通知某个观察者
- public void notifyObservers(Object arg) {
- /*
- * a temporary array buffer, used as a snapshot of the state of
- * current Observers.
- */
- Object[] arrLocal;
- synchronized (this) {
- /* We don't want the Observer doing callbacks into
- * arbitrary code while holding its own Monitor.
- * The code where we extract each Observable from
- * the Vector and store the state of the Observer
- * needs synchronization, but notifying observers
- * does not (should not). The worst result of any
- * potential race-condition here is that:
- * 1) a newly-added Observer will miss a
- * notification in progress
- * 2) a recently unregistered Observer will be
- * wrongly notified when it doesn't care
- */
- if (!changed)
- return;
- arrLocal = obs.toArray();
- clearChanged();
- }
- for (int i = arrLocal.length-1; i>=0; i--)
- ((Observer)arrLocal[i]).update(this, arg);
- }
- //移除所有观察者
- public synchronized void deleteObservers() {
- obs.removeAllElements();
- }
- //设置状态改变
- protected synchronized void setChanged() {
- changed = true;
- }
- //设置状态未改变
- protected synchronized void clearChanged() {
- changed = false;
- }
- //判断状态是否改变
- public synchronized boolean hasChanged() {
- return changed;
- }
- //得到观察者数量
- public synchronized int countObservers() {
- return obs.size();
- }
- }
观察者超类:
java 代码
- public interface Observer {
- void update(Observable o, Object arg);
- }
观察者扩展类:
java 代码
- public class Observer1 implements Observer {
- //注册观察主题, 这个可以在超类中实现
- public void Observer1(){
- Observable observable = new Observable();
- observable.addObserver(this);
- }
- void update(Observable o, Object arg){
- //do our bussiness ......
- System.out.println("O has changed, I get it!");
- }
- }
示例2:
有一个系统, 不定时的收到很多信息,如天气预报, 体育新闻, 国际新闻, 最新歌曲等, 每次有新的信息到达时, 系统将这些信息发送给不同的订阅客户,这些客户都订阅了这些主题中的一个或多个. 客户也可以选择订阅和退定.
这是一个典型的订阅/发布系统: 这些不同信息就相当于不同的主题(Subject), 不同内容的订阅客户就相当于观察者(Observer). 例子以后再写喽!