Java案例怎么实现观察者模式?

wen java案例 59

Java实现观察者模式

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

Java案例怎么实现观察者模式?

基础实现示例

自定义实现方式

import java.util.ArrayList;
import java.util.List;
// 1. 定义观察者接口
interface Observer {
    void update(String message);
}
// 2. 定义被观察者(主题)接口
interface Subject {
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObservers();
}
// 3. 具体被观察者实现
class NewsPublisher implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String news;
    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }
    @Override
    public void detach(Observer observer) {
        observers.remove(observer);
    }
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(news);
        }
    }
    // 业务方法:发布新闻
    public void publishNews(String news) {
        this.news = news;
        System.out.println("新闻发布: " + news);
        notifyObservers();
    }
}
// 4. 具体观察者实现
class PhoneApp implements Observer {
    private String appName;
    public PhoneApp(String appName) {
        this.appName = appName;
    }
    @Override
    public void update(String message) {
        System.out.println(appName + " 收到推送: " + message);
    }
}
class EmailSubscriber implements Observer {
    private String email;
    public EmailSubscriber(String email) {
        this.email = email;
    }
    @Override
    public void update(String message) {
        System.out.println("发送邮件到 " + email + ": " + message);
    }
}
// 5. 测试类
public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 创建被观察者
        NewsPublisher publisher = new NewsPublisher();
        // 创建观察者
        Observer phoneApp = new PhoneApp("新闻客户端");
        Observer emailSubscriber = new EmailSubscriber("user@example.com");
        // 注册观察者
        publisher.attach(phoneApp);
        publisher.attach(emailSubscriber);
        // 发布新闻
        publisher.publishNews("Java 17发布新特性!");
        // 取消订阅
        publisher.detach(emailSubscriber);
        // 再次发布新闻
        publisher.publishNews("AI技术取得重大突破!");
    }
}

使用Java内置的Observable和Observer

import java.util.Observable;
import java.util.Observer;
// 1. 被观察者类(继承Observable)
class WeatherData extends Observable {
    private float temperature;
    private float humidity;
    public void setMeasurements(float temperature, float humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
        // 标识状态已改变
        setChanged();
        // 通知所有观察者
        notifyObservers();
    }
    public float getTemperature() {
        return temperature;
    }
    public float getHumidity() {
        return humidity;
    }
}
// 2. 观察者实现
class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;
    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) o;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
            display();
        }
    }
    public void display() {
        System.out.println("当前温度: " + temperature + "°C, 湿度: " + humidity + "%");
    }
}
class StatisticsDisplay implements Observer {
    private float maxTemp = Float.MIN_VALUE;
    private float minTemp = Float.MAX_VALUE;
    private float tempSum = 0;
    private int numReadings = 0;
    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) o;
            float temp = weatherData.getTemperature();
            tempSum += temp;
            numReadings++;
            if (temp > maxTemp) maxTemp = temp;
            if (temp < minTemp) minTemp = temp;
            display();
        }
    }
    public void display() {
        System.out.println("温度统计 - 最高: " + maxTemp + 
                         "°C, 最低: " + minTemp + 
                         "°C, 平均: " + (tempSum / numReadings) + "°C");
    }
}
// 3. 测试类
public class JavaObserverDemo {
    public static void main(String[] args) {
        // 创建被观察者
        WeatherData weatherData = new WeatherData();
        // 创建观察者
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay();
        // 注册观察者
        weatherData.addObserver(currentDisplay);
        weatherData.addObserver(statisticsDisplay);
        // 更新数据
        System.out.println("=== 第一次更新 ===");
        weatherData.setMeasurements(25.0f, 65.0f);
        System.out.println("\n=== 第二次更新 ===");
        weatherData.setMeasurements(28.0f, 70.0f);
        System.out.println("\n=== 第三次更新 ===");
        weatherData.setMeasurements(22.0f, 80.0f);
    }
}

进阶实现:带事件对象的观察者模式

import java.util.EventListener;
import java.util.EventObject;
import java.util.ArrayList;
import java.util.List;
// 1. 定义事件对象
class DataChangeEvent extends EventObject {
    private String propertyName;
    private Object oldValue;
    private Object newValue;
    public DataChangeEvent(Object source, String propertyName, 
                          Object oldValue, Object newValue) {
        super(source);
        this.propertyName = propertyName;
        this.oldValue = oldValue;
        this.newValue = newValue;
    }
    public String getPropertyName() {
        return propertyName;
    }
    public Object getOldValue() {
        return oldValue;
    }
    public Object getNewValue() {
        return newValue;
    }
}
// 2. 定义事件监听器接口
interface DataChangeListener extends EventListener {
    void onDataChanged(DataChangeEvent event);
}
// 3. 数据模型(被观察者)
class DataModel {
    private List<DataChangeListener> listeners = new ArrayList<>();
    private String name;
    private int value;
    public DataModel(String name, int value) {
        this.name = name;
        this.value = value;
    }
    // 添加监听器
    public void addDataChangeListener(DataChangeListener listener) {
        listeners.add(listener);
    }
    // 移除监听器
    public void removeDataChangeListener(DataChangeListener listener) {
        listeners.remove(listener);
    }
    // 触发事件
    private void fireDataChanged(String propertyName, Object oldValue, Object newValue) {
        DataChangeEvent event = new DataChangeEvent(this, propertyName, oldValue, newValue);
        for (DataChangeListener listener : listeners) {
            listener.onDataChanged(event);
        }
    }
    // 设置名称
    public void setName(String name) {
        String oldName = this.name;
        this.name = name;
        fireDataChanged("name", oldName, name);
    }
    // 设置值
    public void setValue(int value) {
        int oldValue = this.value;
        this.value = value;
        fireDataChanged("value", oldValue, value);
    }
    public String getName() {
        return name;
    }
    public int getValue() {
        return value;
    }
}
// 4. 具体的监听器实现
class ConsoleLogger implements DataChangeListener {
    @Override
    public void onDataChanged(DataChangeEvent event) {
        System.out.println("[日志] 属性 '" + event.getPropertyName() + 
                         "' 从 '" + event.getOldValue() + 
                         "' 变为 '" + event.getNewValue() + "'");
    }
}
class DatabaseUpdater implements DataChangeListener {
    @Override
    public void onDataChanged(DataChangeEvent event) {
        System.out.println("[数据库] 更新记录: " + 
                         event.getPropertyName() + " = " + event.getNewValue());
    }
}
// 5. 测试类
public class AdvancedObserverDemo {
    public static void main(String[] args) {
        // 创建数据模型
        DataModel model = new DataModel("温度传感器", 25);
        // 创建监听器
        DataChangeListener logger = new ConsoleLogger();
        DataChangeListener dbUpdater = new DatabaseUpdater();
        // 注册监听器
        model.addDataChangeListener(logger);
        model.addDataChangeListener(dbUpdater);
        // 修改数据
        System.out.println("=== 第一次修改 ===");
        model.setName("湿度传感器");
        model.setValue(65);
        System.out.println("\n=== 第二次修改 ===");
        model.setValue(70);
        // 移除日志监听器
        model.removeDataChangeListener(logger);
        System.out.println("\n=== 第三次修改(只有数据库更新)===");
        model.setValue(80);
    }
}

使用场景

  1. 事件驱动系统:GUI事件处理、消息推送
  2. 发布-订阅系统:新闻订阅、社交媒体通知
  3. 数据监控:传感器数据、股票价格监控
  4. MVC架构:Model变化通知View更新

优缺点

优点:

  • 抽象耦合,观察者和被观察者只需知道对方接口
  • 支持广播通信
  • 符合开闭原则

缺点:

  • 观察者过多时通知效率降低
  • 如果观察者之间存在循环依赖可能导致系统崩溃
  • 观察者不知道其他观察者的存在

建议在实际项目中根据具体需求选择合适的实现方式,Java 9+推荐使用PropertyChangeListener或自定义事件监听器而非已废弃的Observable类。

抱歉,评论功能暂时关闭!