欢迎访问宙启技术站
智能推送

Java设计模式之观察者模式的示例分析

发布时间:2023-05-14 15:02:34

观察者模式是一种常用的设计模式,主要用于在对象间建立一种一对多的依赖关系,使得当一个对象状态改变时,所有依赖它的对象都能够得到通知并自动更新。通俗的说法就是,观察者模式是一种消息发布/订阅机制,当消息发布时,所有订阅这个消息的对象都会收到通知并作出相应的处理。

下面通过一个简单的示例来分析观察者模式。

假设有这样一个场景:有一个气象站,能够获取当前的温度、湿度、气压等信息,并将这些信息发送给不同的观察者对象,比如天气公告板、手机App、电视机等。同时,当气象站的信息发生变化时,所有的观察者对象都能够得到通知并更新自己的显示内容。

首先,我们需要定义一个气象数据的类,该类包含温度、湿度、气压等属性和相应的getter方法。此外,我们还需要在该类中定义一个方法,用于通知所有观察者对象数据发生了变化。具体代码如下:

public class WeatherData {
    private float temperature; // 温度
    private float humidity; // 湿度
    private float pressure; // 气压

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }

    // 当气象数据发生变化时,通知所有观察者对象
    public void measurementsChanged() {
        // TODO: 通知所有观察者对象
    }
}

接下来,我们需要定义一个观察者接口,该接口包含一个update()方法,在数据发生变化时会被调用。同时,为了将观察者对象注册到气象数据类中,我们还需要在该接口中定义一个register()方法和一个remove()方法。具体代码如下:

public interface Observer {
    // 当数据发生变化时,会被调用
    void update(float temperature, float humidity, float pressure);

    // 将观察者对象注册到气象数据类中
    void register(Subject subject);

    // 将观察者对象从气象数据类中移除
    void remove(Subject subject);
}

接着,我们需要定义一个具体的观察者类,该类实现了上述的Observer接口,具体实现了update()方法和register()/remove()方法。此外,我们还需要在该类中定义一个display()方法,用于显示观察者对象的内容。具体代码如下:

public class WeatherDisplay implements Observer {
    // 定义观察者对象需要观察的气象数据对象
    private Subject weatherData;
    // 温度
    private float temperature;
    // 湿度
    private float humidity;
    // 气压
    private float pressure;

    public WeatherDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        // 将当前观察者对象注册到气象数据对象中
        weatherData.register(this);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        // 更新观察者对象的温度、湿度、气压
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        // 显示观察者对象的内容
        display();
    }

    @Override
    public void register(Subject subject) {
        // 将当前观察者对象注册到指定的气象数据对象中
        this.weatherData = subject;
        subject.register(this);
    }

    @Override
    public void remove(Subject subject) {
        // 将当前观察者对象从指定的气象数据对象中移除
        subject.remove(this);
    }

    public void display() {
        // 显示观察者对象的内容
        System.out.println("Temperature: " + temperature);
        System.out.println("Humidity: " + humidity);
        System.out.println("Pressure: " + pressure);
    }
}

最后,我们需要在WeatherData类中完成measurementsChanged()方法的具体实现,即通知所有观察者对象数据发生了变化。具体代码如下:

public class WeatherData {
    private float temperature; // 温度
    private float humidity; // 湿度
    private float pressure; // 气压
    private List<Observer> observers; // 观察者对象列表

    public WeatherData() {
        observers = new ArrayList<>();
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }

    // 当气象数据发生变化时,通知所有观察者对象
    public void measurementsChanged() {
        // 遍历所有观察者对象,调用它们的update()方法
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    // 注册观察者对象
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    // 移除观察者对象
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    // 设置气象数据
    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged(); // 数据发生变化,通知所有观察者对象
    }
}

至此,以上代码就实现了观察者模式。具体实现过程如下:

1. 定义气象数据类WeatherData,包含温度、湿度、气压等属性。当数据发生变化时,调用measurementsChanged()方法通知所有观察者对象。

2. 定义观察者接口Observer,包含update()方法、register()方法和remove()方法。update()方法在数据发生变化时被调用,register()方法用于将观察者对象注册到指定的气象数据类中,remove()方法用于将观察者对象从指定的气象数据类中移除。

3. 定义具体的观察者类WeatherDisplay,实现了Observer接口。在构造函数中,将当前观察者对象注册到指定的气象数据类中。在update()方法中,更新观察者对象的温度、湿度、气压,并调用display()方法显示观察者对象的内容。

4. 在WeatherData类中,maintain一个观察者对象列表,实现registerObserver()方法、removeObserver()方法和measurementsChanged()方法。registerObserver()方法用于注册观察者对象,removeObserver()方法用于移除观察者对象,measurementsChanged()方法用于通知所有观察者对象数据发生变化。

总的来说,观察者模式是一种十分灵活的设计模式,它将依赖的行为分离出来,让高耦合变成松耦合,不同的观察者可以自由的增加、删除和更新,同时也大大增强了对象之间的交互性。对于使用场景中存在多个订阅者,需及时体现更新等操作时,观察者模式十分有效,它们也可以很好地协同工作,便于单元测试和复用。