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类。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播