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);
}
}
使用场景
- 事件驱动系统:GUI事件处理、消息推送
- 发布-订阅系统:新闻订阅、社交媒体通知
- 数据监控:传感器数据、股票价格监控
- MVC架构:Model变化通知View更新
优缺点
优点:
- 抽象耦合,观察者和被观察者只需知道对方接口
- 支持广播通信
- 符合开闭原则
缺点:
- 观察者过多时通知效率降低
- 如果观察者之间存在循环依赖可能导致系统崩溃
- 观察者不知道其他观察者的存在
建议在实际项目中根据具体需求选择合适的实现方式,Java 9+推荐使用PropertyChangeListener或自定义事件监听器而非已废弃的Observable类。