观察者模式

          观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新。

特点:

1.观察者模式定义了对象之间一对多的关系。

2.主题(也就是可观察者)用一个共同的接口来更新观察者。

3.观察者和可观察者用松耦合的方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口

4.有多个观察者时,不可以依赖特点的通知次序。

 

定义观察者模式:类图

200909141252899046109

观察者模式的组成
1.抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现
2.抽象观察者角色:所有潜在的观察者都必须实现观察者接口,这个接口只有update()一个方法,当主题状态改变时它被调用。

3.具体主题角色(Watched):一个具体主题总是实现主题接口,除了注册和撤销方法之外,具体主题还实现了notifyObservers()方法,此方法用于在状态改变时更新所有当前观察者。

4.具体观察者角色(Watcher):为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。观察者必须注册具体主题,以便接受更新。

 

这个只是一个主题与观察者的设计,观察者自身还需要将信息显示出去。那么再用一个接口,专门来实现展示的功能。

200909141252899313656

源码实现:

/** 
* 主题 
*/ 
public interface Subject { 
  public void registerObserver(Observer o); 
  public void removeObserver(Observer o); 
  public void notifyObservers(); 
}

 

/** 
* 观察者 
*/ 
public interface Observer { 
  public void update(float temp, float humidity, float pressure); 
}

 

/** 
* 布告板 
*/ 
public interface DisplayElement { 
  public void display(); 
}

 

使用java内置的观察者模式

观察者模式在java中有两种实现方式,一是自己写代码实现,另一个是利用java内置的观察者模式来实现。

java API有内置的观察者模式,java.util包内包含最基本的Observer接口与Observable类,这和Subject接口与Observer接口相似。

相关的接口和类如下:

java.util.Observable   主题(可观察者)------class
java.util.Observer       观察者                     -------interface

相关的API如下:

1、java.util.Observable

Observable()
          构造一个带有零个观察者的 Observable。
方法摘要
void addObserver(Observer o)
          如果观察者与集合中已有的观察者不同,则向对象的观察者集合中添加此观察者。
protected  void clearChanged()
          指示对象不再改变,或者它已对其所有的观察者通知了最近的改变,所以 hasChanged 方法将返回 false。
int countObservers()
          返回 Observable 对象的观察者数目。
void deleteObserver(Observer o)
          从对象的观察者集合中删除某个观察者。
void deleteObservers()
          清除观察者列表,使此对象不再有任何观察者。
boolean hasChanged()
          测试对象是否改变。
void notifyObservers()
          如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。
void notifyObservers(Object arg)
          如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。
protected  void setChanged()
          标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。

2、java.util.Observer
void update(Observable o, Object arg)
          只要改变了 observable 对象就调用此方法。

观察API可以发现,java.util.Observable已经对观察者进行管理了,不再需要主题追踪每个观察者了。

import java.util.Observable; 

public class WeatherData extends Observable { 
        private float temperature; 
        private float humidity; 
        private float pressure; 

        public WeatherData() { 
        } 

        /** 
         * 测量值改变了 
         */ 
        public void measurementsChanged() { 
                setChanged();             //设定改变了 
                notifyObservers();    //通知所有的观察者 
        } 

        /** 
         * 重新设定了测量值 
         */ 
        public void setMeasurements(float temperature, float humidity, float pressure) { 
                this.temperature = temperature; 
                this.humidity = humidity; 
                this.pressure = pressure; 
                measurementsChanged(); 
        } 

        public float getTemperature() { 
                return temperature; 
        } 

        public float getHumidity() { 
                return humidity; 
        } 

        public float getPressure() { 
                return pressure; 
        } 
}

 

import java.util.Observable; 
import java.util.Observer; 

public class CurrentConditionsDisplay implements Observer, DisplayElement { 
        Observable observable; 
        private float temperature; 
        private float humidity; 

        public CurrentConditionsDisplay(Observable observable) { 
                this.observable = observable; 
                observable.addObserver(this); 
        } 

        public void update(Observable obs, Object arg) { 
                if (obs instanceof WeatherData) { 
                        WeatherData weatherData = (WeatherData) obs; 
                        this.temperature = weatherData.getTemperature(); 
                        this.humidity = weatherData.getHumidity(); 
                        display(); 
                } 
        } 

        public void display() { 
                System.out.println("Current conditions: " + temperature 
                                + "F degrees and " + humidity + "% humidity"); 
        } 
}

java.util.Observable的黑暗面

1.Observable是一个类(必须设计一个类继承他,如果某类想同时具有Observable类和另一个超累的行为,就会陷入两难,毕竟java不支持多重继承,这就限制了Observable的复用能力。)而不是一个接口,他甚至没有实现一个接口。。

2.Observable将关键的方法保护起来。如将setChanged()方法保护起来,定义为protected,这样就只能使用继承,而无法创建Observable实例并组合到自己的对象中。

 

其他使用观察者模式的地方

除了在java.util中使用观察者模式外,在javaBeans和Swing中也实现了观察者模式。。许多GUI框架也是如此。。

 

参考Head First设计模式和http://lavasoft.blog.51cto.com/62575/201633   http://ttitfly.iteye.com/blog/152512

posted @ 2012-01-12 18:48  zhxiang  阅读(2180)  评论(1编辑  收藏  举报