11.观察者模式(行为型)-灵析社区

菜鸟码转

十一、观察者模式(行为型)

观察者模式是一种行为型设计模式,它定义了对象之间的一对多依赖关系,使得当一个对象发生改变时,所有依赖于它的对象都会自动接收通知并进行更新。

观察者模式通常由两部分组成:主题(Subject)和观察者(Observer)。主题维护着一个观察者列表,并且在状态发生改变时通知这些观察者。观察者则订阅主题的状态,并在状态发生改变时接收通知并进行相应的操作。

观察者模式被广泛地应用于事件驱动系统中,例如用户界面、网络通信和消息队列等领域。通过使用观察者模式,我们可以解耦主题与观察者之间的关系,从而实现更加灵活的设计。

总之,观察者模式提供了一种简单、灵活的方法来处理多个对象之间的一对多依赖关系。它有助于降低系统的耦合度,并且允许我们实现更加灵活的设计。

示例代码

对象间的一对多的依赖关系。

  • 抽象观察者(多的那一方)
package cn.leetcode;


interface Observer {

    void update(float temperature, float humidity, float pressure);

}
  • 抽象被观察者(一的那一方)
package cn.leetcode;


interface Subject {

    // 注册观察者
    void registerObserver(Observer observer);

    // 移除观察者
    void removeObserver(Observer observer);

    // 通知所有观察者
    void notifyObservers();

}
  • 具体被观察者(一的那一方)
package cn.leetcode;

import java.util.ArrayList;
import java.util.List;

// 具体的被观察对象类
class WeatherData implements Subject {

    // 观察者列表
    private List<Observer> observers = new ArrayList<>();

    // 温度
    private float temperature;

    // 湿度
    private float humidity;

    // 气压
    private float pressure; 

    // 设置测量数据,并通知观察者
    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged(); // 数据已改变,通知观察者
    }

    // 数据已改变,通知观察者
    public void measurementsChanged() {
        // 通知所有观察者
        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, humidity, pressure); 
        }
    }
    
}
  • 具体观察者(多的那一方)
package cn.leetcode;

// 具体的观察者类,用于显示当前天气状况
class CurrentConditionsDisplay implements Observer {

    // 温度
    private float temperature;

    // 湿度
    private float humidity;

    // 气压
    private float pressure;

    // 被观察对象
    private Subject weatherData;

    public CurrentConditionsDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        // 注册为观察者
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        // 显示当前天气状况
        display();
    }

    // 显示当前天气状况
    public void display() {
        System.out.println("当前的天气: 华氏度 " + temperature + ",湿度 " + humidity + "%,气压 " + pressure + "。");
    }

}
  • 客户端
package cn.leetcode;

public class Client {

    public static void main(String[] args) {
        // 创建被观察对象
        WeatherData weatherData = new WeatherData(); 
        // 创建观察者
        new CurrentConditionsDisplay(weatherData);
        // 更新数据并通知观察者
        weatherData.setMeasurements(80, 65, 30.4f); 
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 29.2f);
    }

}

输出:

当前的天气: 华氏度 80.0,湿度 65.0%,气压 30.4。
当前的天气: 华氏度 82.0,湿度 70.0%,气压 29.2。
当前的天气: 华氏度 78.0,湿度 90.0%,气压 29.2。

使用 JDK 提供的类实现观察者模式

在 JDK 中,观察者模式已经被封装成了一个工具类 java.util.Observable 和一个接口 java.util.Observer。下面是一个简单的示例代码,演示如何使用这两个类来实现观察者模式:

  • 主题类
package cn.leetcode.jdk;

import java.util.Observable;

// 主题类,继承自 Observable
public class Subject extends Observable {
    private int data;

    public void setData(int data) {
        this.data = data;
        setChanged();
        notifyObservers();
    }

    public int getData() {
        return data;
    }
    
}
  • 观察者类,实现 Observer 接口


package cn.leetcode.jdk;

import java.util.Observable;
import java.util.Observer;

// 观察者类,实现 Observer 接口
public class ObserverA implements Observer {
    
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("观察者 A 收到数据: " + ((Subject) o).getData());
    }
    
}
package cn.leetcode.jdk;

import java.util.Observable;
import java.util.Observer;

public class ObserverB implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("观察者 B 收到数据: " + ((Subject) o).getData());
    }

}
  • 客户端
package cn.leetcode.jdk;

public class Client {

    public static void main(String[] args) {
        Subject subject = new Subject();
        ObserverA observerA = new ObserverA();
        ObserverB observerB = new ObserverB();

        // 注册观察者
        subject.addObserver(observerA);
        subject.addObserver(observerB);

        // 修改主题数据并通知观察者
        subject.setData(10);
        subject.setData(20);
    }

}

输出:

观察者 B 收到数据: 10
观察者 A 收到数据: 10
观察者 B 收到数据: 20
观察者 A 收到数据: 20

在这个示例中,我们创建了一个主题类 Subject,它继承自 Observable 并包含一些数据。当主题数据发生变化时,我们调用 setChanged() 方法标记数据已经改变,并调用 notifyObservers() 方法通知所有观察者。

同时,我们定义了两个观察者类 ObserverA 和 ObserverB,它们实现了 Observer 接口,其中的 update() 方法会在主题数据发生变化时被调用。

在 Client 类中,我们创建了一个 Subject 对象和两个观察者对象,并通过 addObserver() 方法将观察者注册到主题中。随后,我们修改了主题数据并通知了所有观察者,观察者收到通知后输出相应的信息。

总结

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象能够同时监听某一个主题对象,当主题对象发生变化时会自动通知所有观察者对象,使得它们能够及时更新自己的状态。观察者模式的核心是主题和观察者之间的解耦,让它们能够独立地变化和扩展,从而提高了系统的灵活性和可维护性。在观察者模式中,主题通常是一个抽象类或接口,而观察者通常是具体的实现类,它们之间通过注册和通知的方式进行交互。

阅读量:2015

点赞量:0

收藏量:0