观察者模式(Observer Pattern)详解一、模式概述观察者模式是一种行为型设计模式,它定义了对象之间一对多的依赖关系,当一个对象(被观察者)的状态发生改变时,所有依赖于它的对象(观察者)都会得到通知并自动更新。就像微信公众号——当你关注某个公众号(成为观察者),该公众号发布新文章(状态变化)时,所有关注者都会收到推送通知。二、模式结构1. 核心角色text┌─────────────────┐ ┌─────────────────┐ │ Subject │ │ Observer │ │ (目标接口) │──────────│ (观察者接口) │ └────────┬────────┘ └────────┬────────┘ ▲ ▲ │ │ ┌────────┴────────┐ ┌────────┴────────┐ │ ConcreteSubject │ │ ConcreteObserver│ │ (具体目标) │──────────│ (具体观察者) │ └─────────────────┘ 通知 └─────────────────┘2. 角色职责角色名称职责Subject目标接口提供注册、移除和通知观察者的方法ConcreteSubject具体目标维护观察者列表,状态变化时通知所有观察者Observer观察者接口定义更新接口,接收目标的通知ConcreteObserver具体观察者实现更新接口,响应目标的状态变化三、基础实现示例示例:天气预报系统javaimport java.util.ArrayList; import java.util.List; // 1. 观察者接口 interface Observer { void update(float temperature, float humidity, float pressure); } // 2. 目标接口 interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } // 3. 具体目标:天气数据 class WeatherData implements Subject { private ListObserver 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) { observers.remove(o); } @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(); } } // 4. 具体观察者:当前状况显示 class CurrentConditionsDisplay implements Observer { private float temperature; private float humidity; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.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("当前状况: " + temperature + "℃ " + humidity + "% 湿度"); } } // 5. 具体观察者:天气预报显示 class ForecastDisplay implements Observer { private float lastPressure; private float currentPressure; private Subject weatherData; public ForecastDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void update(float temperature, float humidity, float pressure) { lastPressure = currentPressure; currentPressure = pressure; display(); } public void display() { System.out.print("天气预报: "); if (currentPressure lastPressure) { System.out.println("天气转好"); } else if (currentPressure lastPressure) { System.out.println("可能会有降雨"); } else { System.out.println("天气持续稳定"); } } } // 6. 具体观察者:统计显示 class StatisticsDisplay implements Observer { private float maxTemp = Float.MIN_VALUE; private float minTemp = Float.MAX_VALUE; private float tempSum = 0.0f; private int numReadings = 0; private Subject weatherData; public StatisticsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } @Override public void update(float temperature, float humidity, float pressure) { tempSum += temperature; numReadings++; if (temperature maxTemp) { maxTemp = temperature; } if (temperature minTemp) { minTemp = temperature; } display(); } public void display() { System.out.println("温度统计: 平均 " + (tempSum / numReadings) + "℃ 最高 " + maxTemp + "℃ 最低 " + minTemp + "℃"); } } // 客户端使用 public class WeatherStation { public static void main(String[] args) { // 创建被观察者 WeatherData weatherData = new WeatherData(); // 创建观察者(自动注册) CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); // 模拟新的气象数据 System.out.println("=== 第一次更新 ==="); weatherData.setMeasurements(25.5f, 65, 1013.1f); System.out.println("\n=== 第二次更新 ==="); weatherData.setMeasurements(26.2f, 70, 1012.5f); System.out.println("\n=== 第三次更新 ==="); weatherData.setMeasurements(24.8f, 90, 1009.3f); // 移除一个观察者 weatherData.removeObserver(currentDisplay); System.out.println("\n=== 移除当前显示后更新 ==="); weatherData.setMeasurements(27.0f, 60, 1015.0f); } }四、观察者模式的两种实现方式1.推模型(Push)- 以上示例被观察者将详细信息推送给观察者:java// 被观察者主动推送所有数据 interface Observer { void update(float temp, float humidity, float pressure); // 推 } // 观察者被动接收所有数据 class ConcreteObserver implements Observer { public void update(float temp, float humidity, float pressure) { // 接收所有数据,即使只需要部分数据 } }2.拉模型(Pull)- 更灵活观察者主动拉取所需数据:java// 观察者接口 interface Observer { void update(Subject subject); // 只推送被观察者引用 } // 被观察者提供getter方法 interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); // 提供getter方法供观察者拉取数据 float getTemperature(); float getHumidity(); float getPressure(); } // 具体被观察者 class WeatherData implements Subject { private float temperature; private float humidity; private float pres