在上文:深入浅出设计模式二——WeatherData设计(观察者模式)实现一
我们利用了自己缩写的Subject和Observer类完成了天气预报系统。
在JAVA API中已有写好的观察者模式供我们使用,本文将利用它们重新写一个天气预报系统。
在java.util包中有两个类可观察者Observable和观察者Observer。分别相当于Subject类和Observer类。
在Observable类中已经实现了addObserver,deleteObserver,notifyObservers方法,需要注意的是notifyObservers调用前需要调用setChanged标志状态改变,如果要清除状态改变标志则调用clearChanged方法。
UML图如下:
代码如下:
package com.lwf.disign.learn.observer.weatherdata2;
import java.util.Observable;
public class WeatherData extends Observable{
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){}
public float getTemprature(){
return temperature;
}
public float getHumidity(){
return humidity;
}
public float getPressure(){
return pressure;
}
public void measurementsChanged(){
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
package com.lwf.disign.learn.observer.weatherdata2;
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements Observer {
Observable observable;
private float temperature;
private float humidity;
private float pressure;
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.getTemprature();
this.humidity = weatherData.getHumidity();
this.pressure = weatherData.getPressure();
display();
}
}
public void display() {
System.out.println("Temperature:" + temperature + " Humidity:"
+ humidity + " Pressure:" + pressure);
}
}
测试类:
package com.lwf.disign.learn.observer.weatherdata2;
public class WeatherDataTest {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay o1 = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(12, 23, 24);
weatherData.setMeasurements(42, 55, 77);
weatherData.setMeasurements(43, 55, 77);
weatherData.setMeasurements(44, 55, 77);
weatherData.setMeasurements(45, 55, 77);
weatherData.setMeasurements(46, 55, 77);
}
}
输出结果为:
Temperature:12.0 Humidity:23.0 Pressure:24.0
Temperature:42.0 Humidity:55.0 Pressure:77.0
Temperature:43.0 Humidity:55.0 Pressure:77.0
Temperature:44.0 Humidity:55.0 Pressure:77.0
Temperature:45.0 Humidity:55.0 Pressure:77.0
Temperature:46.0 Humidity:55.0 Pressure:77.0
附件有代码文件。
关注变化:
我们看到JAVA内置的Observer模式的实现,它的Observable是一个类而不是一个接口,那么这个设计违背了面向接口编程,而不是面向实现编程的原则。所以如果当你需要从多个类继承的时候那么就不能使用Observale了。所以如果那种情况的话只能象weatherData的第一个实现一样,自己定义一个Subject接口。
其它JAVA类库使用观察者模式的情况
在JAVA SWING中使用的事件模型,给按钮添加事件的行为即是观察者模式。如下例:
package com.lwf.disign.learn.observer.weatherdata2;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class SwingObserverExample {
JFrame frame;
public static void main(String[] args) {
SwingObserverExample s = new SwingObserverExample();
s.go();
}
public void go(){
frame = new JFrame();
JButton button = new JButton("should i do");
button.addActionListener(new AngleListener());
button.addActionListener(new DeviListener());
frame.getContentPane().add(BorderLayout.CENTER,button);
frame.setVisible(true);
}
class AngleListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.out.println("anglelistener");
}
}
class DeviListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.out.println("deviListener");
}
}
}
按钮通过addActionListener把每个观察者加入观察列表。一旦状态发生改变,则触发事件。