观察者模式

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

场景描述:

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

总结

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

相关推荐
老白干9 分钟前
jjwt 0.9.1 在 JDK 11+ 上的两个“坑”与完整解决方案
java·python·log4j
圆山猫7 小时前
[Virtualization](四):Linux KVM/RISC-V 的 vCPU 运行路径
java·linux·risc-v
城管不管7 小时前
ReAct、Plan-and-Execute、Reflection 三大智能 Agent 范式核心区别
java·人工智能·算法·spring·ai·动态规划
IT小白杨7 小时前
从环境制备到自动化工作流:多账号运营的工程化架构拆解
java·经验分享·自动化·安全架构·指纹浏览器
豆瓣鸡8 小时前
算法日记 - Day3
java·开发语言·算法
萧瑟余晖8 小时前
Java深入解析篇九之NIO详解
java·网络·nio
The Chosen One9858 小时前
高进度算法模板速记(待完善)
java·前端·算法
极光代码工作室10 小时前
基于SpringBoot的课程预约系统
java·springboot·web开发·后端开发
Leighteen11 小时前
`try-finally` 里的 `return`:为什么 `finally` 会悄悄改掉返回值、吞掉异常
java·开发语言
名字还没想好☜12 小时前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine