设计模式之观察者模式(java)
2016-12-20 19:21
267 查看
观察者模式 = 主题 + 观察者(也叫订阅者)
观察者订阅一个主题,当主题内容有更新的时候,观察者可以接受到更新通知,在这里还分为俩种获取更新的方式
推送 : 一旦主题有更新,就主动推送更新通知到各个观察者
拉取 : 主题有更新的时候,观察者需要主动去获取更新
下面我们来看一下基于推送的天气预报的例子,气象站是收集天气信息,WeatherData对象来保存气象数据,并且当WeatherData数据变化时,显示装置(CurrentConditionsDisplay)要动态显示数据的改变。
首先先定义Subject主题接口
定义观察者接口Observer
定义显示装置的展示功能接口
定义WeatherData类实现主题接口:
定义观察者实现类并实现显示装置的显示功能接口:
主要的执行类(气象站):
运行结果截图:
上面时我们完全自己定义接口,下面我们看一下jdk原生内置的观察者模式,java.util.Obervable。(改一下上述的代码就可以,也能相互比较一下)
因为jdk帮我们实现了接口,我们就不需要定义Subject和Observer接口了,首先改变以下WeatherData:
再修改一下CurrentConditionsDisplay:
运行结果:
原生的不好的地方大家应该都看到了,就是直接使用继承Observable类来实现观察者模式的,这样会让代码耦合比较紧密,好的设计原则应该是“多用组合,少用继承”。
观察者订阅一个主题,当主题内容有更新的时候,观察者可以接受到更新通知,在这里还分为俩种获取更新的方式
推送 : 一旦主题有更新,就主动推送更新通知到各个观察者
拉取 : 主题有更新的时候,观察者需要主动去获取更新
下面我们来看一下基于推送的天气预报的例子,气象站是收集天气信息,WeatherData对象来保存气象数据,并且当WeatherData数据变化时,显示装置(CurrentConditionsDisplay)要动态显示数据的改变。
首先先定义Subject主题接口
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
定义观察者接口Observer
public interface Observer { public void update(float temp, float humidity, float pressure); }
定义显示装置的展示功能接口
public interface DisplayElement { public void display(); }
定义WeatherData类实现主题接口:
public class WeatherData implements Subject { private ArrayList observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if(i > 0) { observers.remove(i); } } @Override public void notifyObservers() { for (int i=0;i<observers.size();i++) { Observer observer = (Observer)observers.get(i); observer.update(temperature, humidity, pressure); } } public void measurementsChanged() { notifyObservers(); } public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } public void setTemperature(float temperature) { this.temperature = temperature; } public void setHumidity(float humidity) { this.humidity = humidity; } public void setPressure(float pressure) { this.pressure = pressure; } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } }
定义观察者实现类并实现显示装置的显示功能接口:
public 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); //注册当前的观察者 } @Override public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; display(); } @Override public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); } }
主要的执行类(气象站):
public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(80, 65, 30); weatherData.setMeasurements(82, 70, 29); weatherData.setMeasurements(83, 90, 28); } }
运行结果截图:
上面时我们完全自己定义接口,下面我们看一下jdk原生内置的观察者模式,java.util.Obervable。(改一下上述的代码就可以,也能相互比较一下)
因为jdk帮我们实现了接口,我们就不需要定义Subject和Observer接口了,首先改变以下WeatherData:
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 void setTemperature(float temperature) { this.temperature = temperature; } public void setHumidity(float humidity) { this.humidity = humidity; } public void setPressure(float pressure) { this.pressure = pressure; } public float getTemperature() { return temperature; } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } }
再修改一下CurrentConditionsDisplay:
public class CurrentConditionsDisplay implements Observer, DisplayElement { private float temperature; private float humidity; private float pressure; private Observable observable; 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(); this.pressure = weatherData.getPressure(); display(); } } @Override public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); } }
运行结果:
原生的不好的地方大家应该都看到了,就是直接使用继承Observable类来实现观察者模式的,这样会让代码耦合比较紧密,好的设计原则应该是“多用组合,少用继承”。
相关文章推荐
- 如何使用java调用c
- Java常用的输入输出方法
- JAVA泛型详解
- java中将数组、对象、Map、List转换成JSON数据
- slf4j, log4j, logback, java.util.Logging关系
- byte类型转换运算
- Java 8新特性—字符串去重
- LintCode547:两组数的交
- Java代码配置DispatcherServlet
- HDU 1850 - Being a Good Boy in Spring Festival【Nim博弈】
- Java Web 随笔(2):简单的DOM操作
- 03.1 使用普通表单向Spring控制器提交数据
- java反射详解
- Java 获取前一天的24小时
- spring 总结
- JAVA多态学习总结(一)
- SpringMVC 统一返回JSON格式数据到前端
- Jodd-Java的瑞士军刀 demo
- Comparable接口对对象进行排序
- Spring学习之旅(三) Spring MVC配置