一个对象状态变化,其他依赖它的对象都要做出反应?观察者模式为你提供了完美的解决方案,当一个对象变化时,所有依赖它的对象都会收到通知并自动更新。

在实际开发中,很多时候我们希望某个对象的状态变化能即时通知到其他对象,而不用每次都手动更新所有依赖的对象。观察者模式就像是一个通知系统,当某个对象的状态发生变化时,所有订阅了这个对象的“观察者”都会第一时间接到通知,并进行相应的操作。就像是股票市场的行情变化,一旦某只股票的价格波动,所有的投资者(观察者)都会立即得到通知,从而做出决策。

趣味解读:生活中的“天气预报”

想象一下,你每天早晨都通过手机查看天气预报,得知今天是否下雨。这里,天气变化是“被观察者”,而你就是“观察者”。当天气发生变化时,天气预报系统(被观察者)会及时通知你(观察者),你可以根据天气情况决定是否带伞、穿外套等。这就是观察者模式的运作原理:天气变化(被观察者)通知你(观察者)进行相应的反应。

Java代码案例:观察者模式 - 简单的气象站

假设你正在开发一个气象站系统,气象站实时监测温度,并将温度变化通知给所有注册的观察者(比如显示屏、打印机、移动应用等)。通过观察者模式,你可以在不直接依赖每个显示设备的情况下,轻松实现温度变化通知。

// 1. 观察者接口
interface Observer {
    void update(float temperature);
}
​
// 2. 被观察者接口
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
​
// 3. 具体的被观察者 - 气象站
class WeatherStation implements Subject {
    private float temperature;
    private List<Observer> observers = new ArrayList<>();
​
    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyObservers(); // 温度变化时通知所有观察者
    }
​
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
​
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
​
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature); // 将当前温度传递给所有观察者
        }
    }
}
​
// 4. 具体观察者 - 显示屏
class DisplayScreen implements Observer {
    @Override
    public void update(float temperature) {
        System.out.println("Display Screen: Current Temperature is " + temperature + "°C");
    }
}
​
// 5. 具体观察者 - 打印机
class Printer implements Observer {
    @Override
    public void update(float temperature) {
        System.out.println("Printer: Printing current temperature: " + temperature + "°C");
    }
}
​
// 6. 客户端代码
public class Main {
    public static void main(String[] args) {
        // 创建气象站
        WeatherStation weatherStation = new WeatherStation();
​
        // 创建并注册观察者
        DisplayScreen displayScreen = new DisplayScreen();
        Printer printer = new Printer();
​
        weatherStation.registerObserver(displayScreen);
        weatherStation.registerObserver(printer);
​
        // 设置温度,所有观察者会收到通知
        weatherStation.setTemperature(25.5f);
        weatherStation.setTemperature(30.2f);
    }
}

解析:

  • 观察者接口Observer 接口定义了一个 update() 方法,用于接收并处理状态变化的通知。

  • 被观察者接口Subject 接口定义了管理观察者的方法,包括注册、删除和通知观察者。

  • 具体的被观察者 - 气象站WeatherStation 类实现了 Subject 接口,当温度变化时,气象站会通知所有已注册的观察者。

  • 具体观察者 - 显示屏和打印机DisplayScreenPrinter 类分别实现了 Observer 接口,并在收到温度变化通知时进行更新操作。

  • 客户端代码:在 Main 类中,我们创建了气象站对象和两个观察者对象(显示屏和打印机),并注册了这些观察者。当气象站的温度发生变化时,所有观察者都会接收到更新的通知。

运行结果:

Display Screen: Current Temperature is 25.5°C
Printer: Printing current temperature: 25.5°C
Display Screen: Current Temperature is 30.2°C
Printer: Printing current temperature: 30.2°C

实际应用场景:

  1. UI界面更新:观察者模式常用于GUI应用中。当一个模型对象的状态变化时,所有需要显示这些数据的界面(如表格、图表等)都会自动更新,用户界面不需要直接知道这些数据的具体变化。

  2. 事件驱动编程:在一些事件驱动的编程模型中,比如Web开发或前端开发,用户的操作会触发事件,观察者模式可以帮助管理这些事件的响应,确保系统的模块化和解耦。

  3. 社交网络通知系统:例如,社交网络中,当一个用户发布了新动态,所有关注该用户的其他用户都会收到通知。这里,发布者是被观察者,所有关注者是观察者。

总结

观察者模式通过建立一个“观察者”与“被观察者”之间的关系,让多个对象能够在某个对象状态发生变化时及时响应。它的优势在于减少了对象之间的耦合性,提高了系统的灵活性和可扩展性。在很多需要动态更新界面或通知其他对象的场景中,观察者模式都是一个非常有效的设计模式。