观察者模式(Observer Pattern)
观察者模式定义了对象之间的一对多依赖,当一个对象的状态改变时,它的所有依赖者都会收到通知并自动更新。该模式可以让主题和观察者之间松耦合,降低相互之间的依赖性。
一个来自《Head First设计模式》的气象站实例
/*
* 一个Subject接口(主题接口):让实现该接口的所有类都具有以下三种方法,用于注册、删除、更新观察者
*
*/
public interface Subject {
//注册一个观察者
public void registerObserver(Observer ob);
//注销一个观察者
public void removeObserver(Observer ob);
//当主题状态改变时,调用此方法,更新所有观察者
public void notifyObservers();
}
/*
* 一个Observer接口(观察者接口):实现该接口的类必须含有update()方法
*
*/
public interface Observer {
//当气象观测值改变时,主题接口的实现类会把这些状态值作为参数传递给Observer接口实现类的update()方法
public void update(float temperature, float humidity, float pressure);
}
/*
* 一个DiaplayElement接口
*/
public interface DisplayElement {
//用于显示天气信息
public void display();
}
public class WeatherData implements Subject {
//天气信息的三个属性
private float temperature;//温度
private float humidity;//湿度
private float pressure;//气压
private List<Observer> obs;
//构造方法
public WeatherData() {
obs = new ArrayList<Observer>();//创建一个Observer集合
}
//天气信息设置
public void setData(float temperature, float humidity, float pressure) {
//为三个属性赋值
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
changeWeather();//天气信息更改时调用方法
}
//天气信息更改时,更新观察者
public void changeWeather() {
notifyObservers();
}
@Override
public void registerObserver(Observer ob) {
if(!obs.contains(ob)) {
obs.add(ob);
}
}
@Override
public void removeObserver(Observer ob) {
if(obs.contains(ob)) {
obs.remove(ob);
}
}
@Override
public void notifyObservers() {
for(Observer ob : obs) {
ob.update(temperature, humidity, pressure);
}
}
//WeatherData的其他方法。。。
}
/*
* 一个CurrentConditionsDisplay类实现Observer接口和DisplayElement接口:现实中可以有很多种CurrentConditionsDisplay类
*/
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private float pressure;
private Subject weatherData;
//无参构造方法
public CurrentConditionsDisplay(){}
//有参的构造方法:在创建CurrentConditionsDisplay的对象时,传入Subject接口实现类,调用实现类的registerObserver()方法,将观察者类注册进去
public CurrentConditionsDisplay(Subject subject) {
this.weatherData = subject;
weatherData.registerObserver(this);
}
//注销观察者
public void removeObserver() {
weatherData.removeObserver(this);
}
@Override
public void display() {
System.out.println("今天的天气情况: 温度为" + temperature + "\t湿度为" + humidity + "\t气压为" + pressure);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
}
Java内置的观察者模式
让观察者类实现java.util包中的Observer接口,让可观察者继承java.util包中的Observable类
修改过后的代码如下
public class WeatherData extends Observable {
//天气信息的三个属性
private float temperature;//温度
private float humidity;//湿度
private float pressure;//气压
//无参的构造方法
public WeatherData() {}
public void changeWeather() {
setChanged();//标记状态已经改变的事实,只有调用此方法时,才会去更新观察者
notifyObservers();
}
//天气信息设置
public void setData(float temperature, float humidity, float pressure) {
//为三个属性赋值
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
changeWeather();//天气信息更改时调用方法
}
//生成get方法
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
/*
* 一个DiaplayElement接口
*/
public interface DisplayElement {
//用于显示天气信息
public void display();
}
public class CurrentConditionsDisplay implements DisplayElement, Observer {
private Observable observable;
//天气信息的三个属性
private float temperature;//温度
private float humidity;//湿度
private float pressure;//气压
//无参构造方法
public CurrentConditionsDisplay() {}
//有参构造方法
public CurrentConditionsDisplay(Observable obs) {
this.observable = obs;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof WeatherData) {
WeatherData weatherData = (WeatherData) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
this.pressure = weatherData.getPressure();
display();
}
}
@Override
public void display() {
System.out.println("今天的天气情况: 温度为" + temperature + "\t湿度为" + humidity + "\t气压为" + pressure);
}
}
注意:setChanged()
方法。使用Java内置的观察者模式有个缺陷就是,可观察者是继承Observable类,如果可观察者已经继承其他父类,则无法实现观察者模式,由于Java中不支持多继承,因此,在使用该模式时,要视情况而定。
网友评论