一、概述
观察者模式有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己.
二、问题解决
观察者模式提供了一种对象设计,让主题和观察者之间松耦合(松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低 ).
三、模式的角色关系
Subject:它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者,可以注册和删除观察者对象.
Observer:为所有的具体观察者定义一个接口,在得到主题通知时更新自己.
四、实例展示UML图
五、Demo展示
1、Subject接口
package cn.design.observer;
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver();
}
2、Subject的实现类,WeatherData
package cn.design.observer;
import java.util.ArrayList;
public class WeatherData implements Subject{
private ArrayList<Observer> obserList=null;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
obserList=new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
obserList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int index=obserList.indexOf(observer);
if (-1!=index) {
obserList.remove(index);
}
}
@Override
public void notifyObserver() {
if (null!=obserList&&obserList.size()>0) {
for (Observer observer : obserList) {
observer.update(temperature, humidity, pressure);
}
}
// for (int i = 0; i < obserList.size(); i++) {
// Observer observer=obserList.get(i);
// observer.update(temperature, humidity, pressure);
//
// }
}
public void measurementsChanged() {
notifyObserver();
}
public void setMeasurements(float temperature,float humidity,float pressure) {
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
}
3、Observer接口
package cn.design.observer;
public interface Observer {
void update(float temp,float humidity,float pressure);
}
4、DisplayElement接口,测试显示输出结果
package cn.design.observer;
public interface DisplayElement {
void display();
}
5、ObServer的实现类CurrentConditionsDisplay,可以定义更多的观察者,eg:ForecastDisplay、StatisticsDisplay
package cn.design.observer;
public class CurrentConditionsDisplay implements Observer ,DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData=weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("Current temperature is "+temperature+"degree "+" and humidity is %"+humidity);
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature=temp;
this.humidity=humidity;
display();
}
}
6、测试类
package cn.design.observer;
public class WeatherTest {
public static void main(String[] args) {
WeatherData weatherData=new WeatherData();
CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 64, 30.4f);
}
}
六、使用Java内置的观察者模式实现上面demo(Observable、Observer)
1、UML图
2、Observable的实现类WeatherData
package cn.java.observer;
import java.util.Observable;
public class WeatherData extends Observable{
// private ArrayList<Observer> obserList=null;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
// obserList=new ArrayList<>();
}
// @Override
// public synchronized void addObserver(Observer o) {
// obserList.add(o);
// }
// @Override
// public synchronized void deleteObserver(Observer o) {
//
// int index=obserList.indexOf(o);
// if (-1!=index) {
// obserList.remove(index);
// }
// }
public void setMeasurements(float temperature,float humidity,float pressure) {
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
public void measurementsChanged() {
setChanged();
notifyObservers();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
3、Observer的实现类CurrentConditionsDisplay,可以有多个Observer,eg:StatisticsDisplay、etc
package cn.java.observer;
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements Observer{
private float temperature;
private float humidity;
private Observable weatherData;
public CurrentConditionsDisplay(Observable observable) {
this.weatherData=observable;
weatherData.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof WeatherData) {
WeatherData weatherData=(WeatherData) o;
temperature=weatherData.getTemperature();
humidity=weatherData.getHumidity();
display();
}
}
public void display() {
System.out.println("Current temperature is "+temperature+"degree "+" and humidity is %"+humidity);
}
}
4、测试类
package cn.java.observer;
public class WeatherTest {
public static void main(String[] args) {
WeatherData weatherData=new WeatherData();
CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 64, 30.4f);
}
}
七、总结
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体,从而使得各自的变化都不会影响另一边的变化.
设计目的:为交互对象之间的送耦合而设计.
注:文章实例来源于Head First设计模式一书,此书生动有趣,推荐对模式有兴趣的朋友可以去看下,