观察者模式(Observer Pattern)
观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。这种模式也被称作发布 - 订阅(Publish - Subscribe)模式。下面从多个方面详细介绍观察者模式。
模式结构与角色
观察者模式主要包含以下几个角色:
- 主题(Subject):也称为被观察者,它维护一个观察者列表,提供注册、移除观察者的方法,并且在自身状态改变时通知所有注册的观察者。
- 具体主题(Concrete Subject):实现主题接口,当状态发生变化时,调用通知方法来通知所有观察者。
- 观察者(Observer):定义了一个更新方法,当主题状态改变时,该方法会被调用以进行相应的更新操作。
- 具体观察者(Concrete Observer):实现观察者接口,在接收到主题的通知后,执行具体的更新逻辑。
代码示例
以下是一个简单的 Java 代码示例,模拟一个天气站(主题)和多个显示器(观察者)的场景:
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(float temperature, float humidity, float pressure);
}
// 主题接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体主题:天气站
class WeatherStation implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherStation() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
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();
}
}
// 具体观察者:当前天气显示器
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
private Subject weatherStation;
public CurrentConditionsDisplay(Subject weatherStation) {
this.weatherStation = weatherStation;
weatherStation.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
// 客户端代码
public class ObserverPatternExample {
public static void main(String[] args) {
WeatherStation weatherStation = new WeatherStation();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherStation);
weatherStation.setMeasurements(80, 65, 30.4f);
weatherStation.setMeasurements(82, 70, 29.2f);
weatherStation.setMeasurements(78, 90, 29.2f);
}
}
代码解释
- 观察者接口
Observer
:定义了update
方法,当主题状态改变时,观察者通过该方法接收更新信息。 - 主题接口
Subject
:包含registerObserver
用于注册观察者,removeObserver
用于移除观察者,notifyObservers
用于通知所有注册的观察者。 - 具体主题
WeatherStation
:实现了Subject
接口,维护一个观察者列表,当天气测量数据发生变化时,调用notifyObservers
方法通知所有观察者。 - 具体观察者
CurrentConditionsDisplay
:实现了Observer
接口,在update
方法中更新显示的天气信息,并调用display
方法显示当前天气状况。 - 客户端代码:创建了天气站和显示器对象,天气站更新测量数据,显示器接收到通知并显示最新的天气信息。
优点
- 松耦合:主题和观察者之间是松耦合的关系,主题只需要知道观察者实现了
Observer
接口,而不需要了解具体的观察者类。这使得主题和观察者可以独立变化,提高了系统的可维护性和可扩展性。 - 支持广播通信:主题可以同时通知多个观察者,实现了一对多的通信机制。
- 符合开闭原则:可以方便地添加或移除观察者,而不需要修改主题的代码。
缺点
- 观察者过多时性能问题:如果观察者数量过多,通知所有观察者可能会导致性能下降。
- 循环依赖问题:如果主题和观察者之间存在循环依赖,可能会导致系统出现问题,需要小心处理。
应用场景
- 事件处理系统:例如,图形用户界面(GUI)中的按钮点击事件,当按钮被点击(主题状态改变)时,会通知所有注册的事件监听器(观察者)进行相应的处理。
- 消息通知系统:如社交网络中的消息推送,当用户发布新消息(主题状态改变)时,会通知所有关注该用户的其他用户(观察者)。
- 股票价格监控系统:股票价格(主题)发生变化时,会通知所有关注该股票的投资者(观察者)。
Java设计模式 文章被收录于专栏
设计模式是软件开发中针对反复出现的问题所总结归纳出的通用解决方案,它可以帮助开发者更高效地构建软件系统,提升代码的可维护性、可扩展性和可复用性。