5.1、介绍
观察者(Observer)模式:对象之间多对一依赖的一种设计方案,被依赖的对象称为Subject(一),依赖的对象称为Observer(多)。Subject给Observer通知发生的变化。
观察者模式又称为发布-订阅模式、模型-视图模式。
这种类型的设计模式属于行为型模式。
5.2、代码支撑
设计一个天气预报系统,可以展示天气信息,并将天气变化信息推送给第三方。
首先设计一个接口 Subject.java
,里面有三个方法需要让类 WeatherData.java
来实现 :
public interface Subject {
public void registerObserver(Observer o);// 注册第三方观察者
public void removeObserver(Observer o);// 移除第三方观察者
public void notifyObserver();// 通知第三方观察者
}
再创建一个观察者接口 Observer.java
,里面的方法需要由第三方观察者 CurrentConditions.java
实现:
public interface Observer {
public void update(float temperature, float pressure, float humidity);// 更新天气信息
}
子类 CurrentConditions.java
是第三方观察者的具体类:
public class CurrentConditions implements Observer {
private float temperature;// 当前天气的温度数值
private float pressure;// 当前天气的气压数值
private float humidity;// 当前天气的湿度数值
// 更新天气信息
@Override
public void update(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
// 显示天气信息
private void display() {
System.out.println("当前温度数值:" + temperature);
System.out.println("当前气压数值:" + pressure);
System.out.println("当前湿度数值:" + humidity);
}
}
类 WeatherData.java
是核心,实现了 Subject.java
接口。包含最新的天气情况;含有第三方观察者集合(使用ArrayList 管理);并且当数据更新时,主动调用 ArrayList ,通知所有的第三方天气变化信息:
import java.util.ArrayList;
public class WeatherData implements Subject {
private float temperature;// 当前天气的温度数值
private float pressure;// 当前天气的气压数值
private float humidity;// 当前天气的湿度数值
private ArrayList<Observer> observers;// 第三方观察者
public WeatherData() {
observers = new ArrayList<Observer>();
}
public float getTemperature() { return temperature; }
public float getPressure() { return pressure; }
public float getHumidity() { return humidity; }
// 数据变化
public void dataChange(){
notifyObserver();
}
// 更新天气数据
public void setData(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
dataChange();
}
// 注册第三方观察者
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
// 移除第三方观察者
@Override
public void removeObserver(Observer o) {
// 判断observers里面有没有对象
if (observers.contains(o)) {
observers.remove(o);
}
}
// 通知第三方观察者
@Override
public void notifyObserver() {
for (int i=0; i<observers.size(); i++){
observers.get(i).update(this.temperature, this.pressure, this.humidity);
}
}
}
代码搭建完毕,下面是客户端 Client.java
的测试:
public class Client {
public static void main(String[] args) {
// 创建一个WeatherData
WeatherData weatherData = new WeatherData();
// 创建一个第三方观察者currentConditions
CurrentConditions currentConditions = new CurrentConditions();
// 将该第三方观察者注册到WeatherData里面
weatherData.registerObserver(currentConditions);
// 测试
System.out.println("请第三方观察者注意,天气变化信息如下:");
weatherData.setData(10f, 100f, 30.0f);
}
}
控制台运行结果如下:
5.3、总结
观察者模式优点:
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
- 目标与观察者之间建立了一套触发机制。
观察者模式缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。