观察者模式

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

场景描述:

我们可以将一个气象站作为"被观察者"(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是具体的观察者,它们在接收到通知后会更新自己的显示内容。

总结

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

相关推荐
SimonKing3 分钟前
5分钟学会!把代码从本地推送到 GitHub,就是这么简单
java·后端·程序员
玹外之音4 分钟前
Spring AI 11 种文档切割策略全解析
java·spring·ai编程
Java练习两年半22 分钟前
互联网大厂 Java 求职面试:技术栈与微服务深度解析
java·微服务·面试·技术栈
Seven9728 分钟前
类字节码:揭开Java虚拟机运行机制的神秘面纱
java
lang201509281 小时前
从零开始掌握 Logback:Java 日志框架的“Hello World”实战指南
java·单元测试·logback
lang201509281 小时前
Logback 过滤器深度指南:从“三值逻辑”到高性能拦截
java·网络·logback
左左右右左右摇晃1 小时前
Java 对象:创建方式与内存回收机制
java·笔记
JMchen1231 小时前
企业级图表组件库完整实现
android·java·经验分享·笔记·canvas·android-studio
java1234_小锋9 小时前
Java高频面试题:Redis的Key和Value的设计原则有哪些?
java·redis·面试
iPadiPhone9 小时前
流量洪峰下的数据守护者:InnoDB MVCC 全实现深度解析
java·数据库·mysql·面试