观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它依赖着都会收到通知并更新。
设计原则:为了交互对象之间松耦合设计而努力。
想到了C#里边的委托好像挺像的
例子:实现一个气象站
代码:
Observer.java
package proj.wxh.observer; /** * 观察者模式-->观察者 */ public interface Observer { /** * 数据更新通知 */ public void update(float temp,float humi, float pressure); }
|
Subject.java
package proj.wxh.subject;
import proj.wxh.observer.Observer;
/** * 观察者模式-->主题 */ public interface Subject { /** * 注册观察者 */ public void registerObserver(Observer o); /** * 移除观察者 */ public void removeObserver(Observer o); /** * 通知信息给观察者 */ public void notifyObservers(); }
|
WeatherData.java
package proj.wxh.subject;
import java.util.ArrayList;
import proj.wxh.observer.Observer; /** * 继承自观察者接口,多用接口少用继承 */ public class WeatherData implements Subject { private ArrayList observers;// 观察者模式 private float temp;// 温度 private float humi;// 湿度 private float pressure;// 气压
public WeatherData() { observers=new ArrayList(); }
@Override public void registerObserver(Observer o) { // 注册观察者 observers.add(o); }
@Override public void removeObserver(Observer o) { // 删除观察者 if(observers.size()>0){ observers.remove(o); } }
@Override public void notifyObservers() { // 通知观察者:遍历通知 for(Object o : observers){ Observer ob=(Observer)o; // 更新数据 ob.update(temp, humi, pressure); } }
/** * 通知新值 */ public void measurementsChanged(){ notifyObservers(); }
/** * 设置相关的值 */ public void setMeassurements(float temp,float humi, float pressure){ this.temp = temp; this.humi = humi; this.pressure = pressure; measurementsChanged(); } } |
DisplayElement.java
package proj.wxh.display; /** * 显示器 */ public interface DisplayElement { /** * 显示信息 */ public void display(); }
|
CurrentConditionDisplay.java
package proj.wxh.display;
import proj.wxh.observer.Observer; import proj.wxh.subject.Subject; /** * 布告栏:订阅主题-->subject */ public class CurrentConditionalDisplay implements Observer, DisplayElement { // 相关数据 private float temp; private float humi; private float pressure; // 订阅的主题 private Subject subject;
public CurrentConditionalDisplay(Subject subject) { this.subject=subject; // 注册主题 subject.registerObserver(this); }
@Override public void display() { System.out.println ("目前温度:"+this.temp+"\n目前湿度:"+this.humi+"\n目前气压:"+this.pressure); }
@Override public void update(float temp, float humi, float pressure) { this.temp=temp; this.humi=humi; this.pressure=pressure; display(); }
} |
AppMain.java
package proj.wxh.app;
import proj.wxh.display.CurrentConditionalDisplay; import proj.wxh.subject.Subject; import proj.wxh.subject.WeatherData;
public class AppMain {
public static void main(String[] args) { // 建立wd主题对象 WeatherData wd=new WeatherData(); // 创建观察者,并订阅主题对象 CurrentConditionalDisplay ccd=new CurrentConditionalDisplay(wd); // 模拟更新测量 wd.setMeassurements(23.4f, 57, 1022); } } |
Java内置的观察者模式
主要用到Observable[可被观察]类和Observer[观察者]接口
Observable[可被观察]类用于创建可以观测到你的程序中其他部分的子类。当这种子类的对象发生变化时,观测类被通知。同时观测类必须实现定义了update()方法的Observer接口。
Observer[观察者]接口实现update方法,这个方法在notifyObservers()方法被调用时触发。
代码:
CuurentConditionalDisplay.java
package proj.wxh.display;
import java.util.Observable; import java.util.Observer; import proj.wxh.subject.WeatherData;
public class CurrentConditionalDisplay implements Observer, DisplayElement { // 相关数据 private float temp; private float humi; private float pressure; // 指定可以被观察的对象 private Observable observable;
public CurrentConditionalDisplay(Observable observable) { this.observable=observable; // 登记观察者对象 observable.addObserver(this); }
@Override public void display() { System.out.println ("目前温度:"+this.temp+"\n目前湿度:"+this.humi+"\n目前气压:"+this.pressure); }
/** * 实现update方法:当被观察者发送通知时,接受通知 */ @Override public void update(Observable o, Object arg) { if (o instanceof WeatherData) {// 判断被观察者类型 WeatherData wd = (WeatherData)o; this.temp=wd.getTemp(); this.humi=wd.getHumi(); this.pressure=wd.getPressure(); } display(); } }
|
WeatherData.java
package proj.wxh.subject;
import java.util.Observable; /** * 继承自观察者接口,多用接口少用继承 * 所有的注册、添加、删除和通知代码由Observable类来代劳 */ public class WeatherData extends Observable{// 继承自Observable表示我可以被观察 private float temp;// 温度 private float humi;// 湿度 private float pressure;// 气压
public WeatherData() {}
/** * 通知新值 */ public void measurementsChanged(){ // 改变状态标志,因为内部状态标志只有为true时才执行通知 setChanged(); // 通知其所有observers notifyObservers(); }
/** * 设置相关的值 */ public void setMeassurements(float temp,float humi, float pressure){ this.temp = temp; this.humi = humi; this.pressure = pressure; measurementsChanged(); }
/** * getter获取值 */ public float getTemp() { return temp; }
public float getHumi() { return humi; }
public float getPressure() { return pressure; } }
|
AppMain.java代码和上面一样。
测试结果:
目前温度:23.4 目前湿度:57.0 目前气压:1022.0
|
大部分东西都参考head first设计模式,有兴趣的可以看一下