观察者模式

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

场景描述:

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

总结

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

相关推荐
徐徐同学2 小时前
cpolar为IT-Tools 解锁公网访问,远程开发再也不卡壳
java·开发语言·分布式
Mr.朱鹏3 小时前
Nginx路由转发案例实战
java·运维·spring boot·nginx·spring·intellij-idea·jetty
白露与泡影4 小时前
2026版Java架构师面试题及答案整理汇总
java·开发语言
历程里程碑4 小时前
滑动窗口---- 无重复字符的最长子串
java·数据结构·c++·python·算法·leetcode·django
qq_229058015 小时前
docker中检测进程的内存使用量
java·docker·容器
我真的是大笨蛋5 小时前
InnoDB行级锁解析
java·数据库·sql·mysql·性能优化·数据库开发
钦拆大仁5 小时前
Java设计模式-单例模式
java·单例模式·设计模式
小手cool5 小时前
在保持数组中对应元素(包括负数和正数)各自组内顺序不变的情况下,交换数组中对应的负数和正数元素
java
笨手笨脚の5 小时前
深入理解 Java 虚拟机-04 垃圾收集器
java·jvm·垃圾收集器·垃圾回收
skywalker_115 小时前
Java中异常
java·开发语言·异常