定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 设计原则:
为了交互对象之间的松耦合设计而努力。 主题和观察者定义了一对多的关系,参见报纸订阅服务,报社是主题,用户是观察者们。
出版方+订阅者=观察者模式:
1、当报社出版新的报纸时,会推送给用户。只要是报社的订户,就会一直收到新报纸。
2、取消报纸订阅服务,就不会收到新报纸。
3、只要报社还在运营,就会一直有人向报社订阅报纸或取消订阅。 主题向观察者推送消息,有两种推送消息的方式,“推”和“拉”。 实例:建立一个气象观测站,WeatherData对象知道如何从气象站获取最新数据,随即显示在布告板上。
以下是“推”的方式:主题推送数据给观察者。
Java由内置的观察者模式API,但以下用自定义的观察者模式来实现“推”方式: package mypackage; public interface Subject { //主题接口
public void registerObserver(Observer o);//注册观察者
public void removeObserver(Observer o);//移除观察者
public void notifyObservers(); //通知更新
} package mypackage; public interface Observer { //观察者接口
public void update(float temp,float humidity,float pressure);
} package mypackage; public interface DisplayElement { //布告板接口
public void display();
} package mypackage; import java.util.ArrayList; public class WeatherData implements Subject { //具体的主题 WeatherData
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();
} } package mypackage; public class CurrentConditionDisplay implements Observer, DisplayElement {//具体的观察者,一个对象就是一个观察者
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionDisplay(Subject weatherData) {
this.weatherData=weatherData;
weatherData.registerObserver(this);
} @Override
public void display() {
System.out.println("Current conditions:"+temperature+"F degrees and"+humidity+"%humidity"); } @Override
public void update(float temperature, float humidity, float pressure) {//获取更新数据
this.temperature=temperature;
this.humidity=humidity;
display(); } } package mypackage; public class WeatherStation { public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentDisplay=new CurrentConditionDisplay(weatherData);//创建一个观察者实例
weatherData.setMeasurements(80, 65, 30.4f);//赋值气象数据
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f); } } 以下是“拉”的方式:
利用Java内置API实现:
package mypackage; public interface DisplayElement { //自定义的布告板接口
public void display();
} package mypackage; import java.util.Observable;//Java内置的主题类 public class WeatherData extends Observable{
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {}
public void measurementsChangerd() {
setChanged(); //需要,把changed标志设置为true,notifyObservers()才会通知观察者
notifyObservers();
}
public void setMeasurements(float temperature,float humidity,float pressure) {
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChangerd();
} public float getTemperature() {
return temperature;
} public float getHumidity() {
return humidity;
} public float getPressure() {
return pressure;
}
}
package mypackage; import java.util.Observable;
import java.util.Observer; //Java内置的观察者接口 public class CurrentConditionsDisplay implements Observer, DisplayElement{
Observable observable;
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable=observable;
observable.addObserver(this);
}
@Override
public void display() {
System.out.println("Current conditions:"+temperature+"F degrees and"+humidity+"%humidity");
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof WeatherData) {
WeatherData weatherData = (WeatherData)o;
this.temperature=weatherData.getTemperature(); //“拉”数据
this.humidity=weatherData.getHumidity();
display();
}
} } package mypackage; public class WeatherStation { public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f); } } Java内置的Observable是一个类,类是单继承的,限制了复用潜力。没有Observable接口也无法建立自己的实现
和Java内置的ObserverAPI搭配使用也无法换成另一套实现,比如setChanged()是受保护的,除非继承,
否则无法创建Observable实例并组合到自己的对象中。