观察者模式

在观察者设计模式中,一个对象(被观察者)维护一系列依赖于它的对象(观察者),当被观察者的状态发生变化时,它会通知所有的观察者。使用观察者模式可以实现解耦,被观察者不需要关心观察者的具体实现,观察者只需注册到被观察者即可。

场景描述:

我们可以将一个气象站作为"被观察者"(WeatherStation),它会定期检测温度、湿度和气压。多个显示面板作为"观察者"(Observer),当气象站更新天气信息时,所有的观察者都会收到通知并显示最新数据。

代码实现

1. 定义 Subject 接口(被观察者)
java 复制代码
import java.util.ArrayList;
import java.util.List;

interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}
2. 定义 Observer 接口(观察者)
java 复制代码
interface Observer {
    void update(float temperature, float humidity, float pressure);
}
3. 实现 WeatherStation 类(具体的被观察者)
java 复制代码
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 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 setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    public void measurementsChanged() {
        notifyObservers();
    }
}
4. 实现具体的观察者类
4.1 CurrentConditionsDisplay(当前天气显示面板)
java 复制代码
class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    @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 + "C degrees and " + humidity + "% humidity.");
    }
}
4.2 StatisticsDisplay(天气统计显示面板)
java 复制代码
class StatisticsDisplay implements Observer {
    private float maxTemp = 0.0f;
    private float minTemp = 200;
    private float tempSum = 0.0f;
    private int numReadings;

    @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("Avg/Max/Min temperature = " + (tempSum / numReadings) + "/" + maxTemp + "/" + minTemp);
    }
}
4.3 ForecastDisplay(天气预报显示面板)
java 复制代码
class ForecastDisplay implements Observer {
    private float currentPressure = 29.92f;
    private float lastPressure;

    @Override
    public void update(float temperature, float humidity, float pressure) {
        lastPressure = currentPressure;
        currentPressure = pressure;
        display();
    }

    public void display() {
        System.out.print("Forecast: ");
        if (currentPressure > lastPressure) {
            System.out.println("Improving weather on the way!");
        } else if (currentPressure == lastPressure) {
            System.out.println("More of the same");
        } else if (currentPressure < lastPressure) {
            System.out.println("Watch out for cooler, rainy weather");
        }
    }
}
5. 测试代码
java 复制代码
public class WeatherStationDemo {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();

        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay();
        ForecastDisplay forecastDisplay = new ForecastDisplay();

        // 注册观察者
        weatherStation.registerObserver(currentDisplay);
        weatherStation.registerObserver(statisticsDisplay);
        weatherStation.registerObserver(forecastDisplay);

        // 模拟气象站数据变化
        weatherStation.setMeasurements(28, 65, 30.4f);
        weatherStation.setMeasurements(27, 70, 29.2f);
        weatherStation.setMeasurements(26, 90, 29.2f);
    }
}

输出结果

plaintext 复制代码
Current conditions: 28.0C degrees and 65.0% humidity.
Avg/Max/Min temperature = 28.0/28.0/28.0
Forecast: Improving weather on the way!
Current conditions: 27.0C degrees and 70.0% humidity.
Avg/Max/Min temperature = 27.5/28.0/27.0
Forecast: Watch out for cooler, rainy weather
Current conditions: 26.0C degrees and 90.0% humidity.
Avg/Max/Min temperature = 27.0/28.0/26.0
Forecast: More of the same

代码解释

  1. Subject接口WeatherStation实现了Subject接口,负责维护观察者列表并通知所有观察者。
  2. Observer接口 :不同的显示面板实现了Observer接口,每当气象站数据更新时,这些观察者会自动收到通知。
  3. WeatherStation类:当气象站的测量数据(温度、湿度、气压)发生变化时,会通知所有注册的观察者。
  4. Observer实现类CurrentConditionsDisplayStatisticsDisplayForecastDisplay是具体的观察者,它们在接收到通知后会更新自己的显示内容。

总结

观察者模式很好地解耦了数据源(气象站)和观察者(显示面板)。通过这种模式,当气象站的数据变化时,所有观察者都会自动收到通知并更新显示,扩展性好且易于维护。

相关推荐
Flittly3 分钟前
【AgentScope Java新手村系列】(10)实战-多Agent天气助手
java·spring boot·spring
李少兄11 分钟前
从原理到实战:Spring IoC/DI 核心知识体系与高频面试题全解
java·后端·spring
飞天狗11135 分钟前
零基础JavaWeb入门——第五课第二小节:九大内置对象 · 第2个:response(响应对象)
java·开发语言
许彰午42 分钟前
39_Java单元测试JUnit入门
java·junit·单元测试
shushangyun_43 分钟前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
JAVA9651 小时前
JAVA面试-JVM篇 03-JVM运行时数据区哪些是线程私有的哪些是共享的
java·jvm·面试
于先生吖1 小时前
教育类Java实战项目:在线错题整理平台分层架构设计与接口源码解析
java·开发语言
慧一居士1 小时前
Feign的GET请求如何传递对象参数?
java·spring cloud
开发小能手-roy2 小时前
Java集合框架选型指南:从ArrayList到ConcurrentSkipListMap
java·开发语言
凡人叶枫2 小时前
Effective C++ 条款41:了解隐式接口和编译期多态
java·开发语言·c++·effective c++