观察者模式的核心是订阅、通知,是个非常有用的设计模式,我们下面就来学习下。
场景描述
书中描述了一个气象数据更新的场景。大概意思是,气象站数据会不定时更新,有好几种布告板需要实时显示,而且必须可扩展,可以随时添加、删除布告板。这种情况下就可以使用到订阅通知模式了。这个场景比较简单,实现起来也不复杂,下面就直接看看代码。
代码示例
定义主题接口
1234567public interface Subject {public void registerObserver(Observer o);public void removeObserver(Observer o);public void notifyObserver();}定义观察者接口,以及显示接口。其中Observer接口是核心,DisplayElement接口是为了指明布告板是需要UI显示出来,因为我们也可以实现一个不需要显示的观察者,抽出单独的接口会更灵活。
1234567public interface Observer {public void update(float temperature, float humidity, float pressure);}public interface DisplayElement {public void display();}实现主题,该实现的核心就在于WeatherData对象中保存了所有观察者对象,通过调用各个观察者的update方法,来实现数据变更通知。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162public class WeatherData implements Subject {public List<Observer> observers;private float temperature;private float humidity;private float pressure;public WeatherData() {observers = new ArrayList<>();}/*** 注册观察者** @param o*/public void registerObserver(Observer o) {observers.add(o);}/*** 取消订阅** @param o*/public void removeObserver(Observer o) {int i = observers.indexOf(o);if (i >= 0) {observers.remove(i);}}/*** 通知观察者数据变更*/public void notifyObserver() {observers.forEach(v -> v.update(temperature, humidity, pressure));}/*** 当气象站得到更新观测值时,通知观察者*/public void measurementsChanged() {notifyObserver();}/*** 用来模拟数据变更** @param temperature* @param humidity* @param pressure*/public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.pressure = pressure;this.humidity = humidity;measurementsChanged();}}实现用于显示当前数据的布告板
123456789101112131415161718192021222324public class CurrentConditionsDisplay implements Observer, DisplayElement {private float temperature;private float humidity;private float pressure;private Subject weatherData;public CurrentConditionsDisplay(Subject weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);}public void update(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;display();}public void display() {System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity and " + pressure + " pa");}}测试
123456789public class WeatherStation {public static void main(String[] args) {WeatherData weatherData = new WeatherData();CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);weatherData.setMeasurements(80, 65, 30.4f);weatherData.setMeasurements(82, 70, 29.2f);weatherData.setMeasurements(78, 90, 39.2f);}}
这个模式看起来好像比较简单,我们看看它的定义:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。所以整个核心就在于WeatherData中保存了所有Observer对象。
总结
观察者模式就记录到这儿了,感觉意犹未尽,却又不知如何发力,可能是道行太浅,继续修炼吧。