观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象状态改变时,它的所有依赖者都会收到通知并自动更新。
观察者模式中,分为推和拉两种模式。
推模式,即主题对象向观察者对象推送状态值,不管观察者对象是否需要,并且推送全部数据或者部分数据。
拉模式,即主题对象通知观察者对象状态值已改变,观察者根据自己需要决定是否主动到主体对象中获取详细信息。
两种模式的比较
1、推模型是假定主题对象知道观察者需要的数据;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
2、推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要。
说明:
1、观察者模式将观察者和主题(被观察者)的对象分离开,实现了两者的松耦合。提高了应用程序的可维护性和重用性;
2、JAVA API 内置有观察者模式。位于java.util包,包含有最基本的Observer接口与Observable类,分别对应观察者和主题;
3、主题仅需要把实时的状态值更新给观察者即可,而不需要知道观察者怎样处理数据或者其他细节。
场景:
1、对于一个对象的状态值需要实时更新到其他任何几个对象。如气象站检测的天气数据,要实时更新给气象网站的布告板。
/** * 主题类接口。 * 用来定义注册观察者、移除观察者、通知更新等方法 * @author xiabaike */ public interface Subject { /** * 注册观察者 * */ public void registerObserver(Observer o); /** * 移除观察者 * */ public void removeObserver(Observer o); /** * 当状态改变时,调用此方法,通知所有观察者 * */ public void notifyObservers(); } |
/** * 观察者类接口。 * 当主题状态发生改变时,主题会把这些状态值当做方法的参数,传送给观察者。 * @author xiabaike * */ public interface Observer { /** * 当主题状态发生改变时,主题会把这些状态值当做方法的参数,传送给观察者 * 所有观察者都必须实现此方法,以实现观察者接口 * */ public void update(float temp, float humidity, float pressure); } |
/** * 展示。在布告板上显示内容 * */ public interface DisplayElement { /** * 当布告板需要显示时,调用此方法 * */ public void display(); } |
/** * 天气数据类。产生更新状态值,并通知布告板观察者 * */ public class WeatherData implements Subject{ // 用来存放所有的观察者 private List<Observer> observerList; private float tempPerature; private float humidity; private float pressure; public WeatherData() { observerList = new ArrayList<Observer>(); } public void registerObserver(Observer o) { observerList.add(o); } public void removeObserver(Observer o) { if(observerList.contains(o)) { observerList.remove(o); } } public void notifyObservers() { for(int i = 0; i < observerList.size(); i++) { observerList.get(i).update(tempPerature, humidity, pressure); } } /** * 当从气象站得到更新观测值时,通知观察者 * */ public void setMeasurements(float temperature, float humidity, float pressure) { this.tempPerature = temperature; this.humidity = humidity; this.pressure = pressure; notifyObservers(); } } |
/** * 具体布告板实现类。获取状态值,并展示 * */ public class CurrentConditionsDisplay implements Observer, DisplayElement{ private float tempPerature; private float humidity; private float pressure; private Subject subject; public CurrentConditionsDisplay(Subject subject) { this.subject = subject; this.subject.registerObserver(this); } public void update(float temp, float humidity, float pressure) { this.tempPerature = temp; this.humidity = humidity; this.pressure = pressure; display(); } public void display() { System.out.println("Current conditions: " + tempPerature +", "+ humidity +", "+ pressure); } } |
/** * 主类,模拟气象站产生检测数据,并更新给布告板 * */ public class WeatherStation { public static void main(String[] args) { WeatherData subject = new WeatherData(); CurrentConditionsDisplay observer = new CurrentConditionsDisplay(subject); subject.setMeasurements(1, 2, 3); } } |
参考资料:《Head First 设计模式》
http://www.cnblogs.com/itTeacher/archive/2012/12/03/2800129.html
http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html