观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式通常用于实现事件处理系统。
通过观察者模式,主题(Subject)和观察者(Observer)之间的耦合度降低了。主题只需维护一个观察者列表,并负责通知观察者,而不需要关心观察者的具体实现。
观察者模式广泛应用于需要事件通知的场景,以下是一些典型的应用场景:
GUI框架中的事件处理:
数据模型与视图的同步:
发布-订阅系统:
日志系统:
在观察者模式中,主要涉及两个角色:主题(Subject)和观察者(Observer)。
主题(Subject):
registerObserver(Observer o)
:注册一个观察者。removeObserver(Observer o)
:移除一个观察者。notifyObservers()
:通知所有注册的观察者。观察者(Observer):
update
方法,用于接收主题的通知并更新自身状态。解耦:
灵活性:
符合开闭原则:
可能导致性能问题:
可能导致内存泄漏:
不确定的通知顺序:
Java 提供了一套内置的观察者模式实现,通过 java.util.Observer
接口和 java.util.Observable
类来实现。
java.util.Observer
接口Observer
接口只有一个方法,需要观察者实现:
public interface Observer {
void update(Observable o, Object arg);
}
java.util.Observable
类Observable
类提供了一些方法来管理和通知观察者:
public class Observable {
// 添加观察者
public synchronized void addObserver(Observer o) { ... }
// 删除观察者
public synchronized void deleteObserver(Observer o) { ... }
// 通知所有观察者
public void notifyObservers() { ... }
// 通知所有观察者,并传递参数
public void notifyObservers(Object arg) { ... }
// 标记状态已改变
protected synchronized void setChanged() { ... }
// 清除已改变标记
protected synchronized void clearChanged() { ... }
// 检查状态是否已改变
public synchronized boolean hasChanged() { ... }
// 获取观察者数量
public synchronized int countObservers() { ... }
}
import java.util.Observable;
import java.util.Observer;
// 具体的主题类
class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public void measurementsChanged() {
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
// 具体的观察者类
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
observable.addObserver(this);
}
@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("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
// 测试代码
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
}
}
虽然 Java 内置的观察者模式实现已经很方便,但有时我们需要自定义实现以满足特定需求。以下是一个自定义实现的示例:
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(float temperature, float humidity, float pressure);
}
// 主题接口
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// 具体的主题类
class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
// 具体的观察者类
class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Subject weatherData) {
weatherData.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
// 测试代码
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
}
}
java.util.Observer
和 java.util.Observable
的示例首先,我们来看一个使用 Java 内置的 Observer
和 Observable
来实现观察者模式的示例。
import java.util.Observable;
public class WeatherData extends Observable {
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() {
setChanged();
notifyObservers();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
import java.util.Observable;
import java.util.Observer;
public 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("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
weatherData.addObserver(currentDisplay);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
接下来,我们来看一个自定义实现观察者模式的示例。
import java.util.ArrayList;
import java.util.List;
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
public interface Observer {
void update(float temperature, float humidity, float pressure);
}
public class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public void measurementsChanged() {
notifyObservers();
}
}
public class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
weatherData.registerObserver(currentDisplay);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
通过这两个示例,我们可以看到如何使用 Java 内置的 Observer
和 Observable
实现观察者模式,以及如何自定义实现观察者模式。
观察者模式在实际项目中有许多典型的应用场景,包括但不限于:
MVC(Model-View-Controller)架构是一个非常经典的设计模式,广泛应用于各种软件开发中。观察者模式在 MVC 架构中扮演了重要角色,特别是在 Model 和 View 之间的交互中。
在 MVC 中,Model 作为主题(Subject),View 作为观察者(Observer)。当 Model 中的数据发生变化时,View 会自动更新,以反映新的数据状态。
我们以一个简单的股票价格更新系统为例,展示观察者模式在 MVC 架构中的应用。
import java.util.Observable;
public class StockData extends Observable {
private String stockSymbol;
private float stockPrice;
public StockData(String stockSymbol) {
this.stockSymbol = stockSymbol;
}
public void setStockPrice(float stockPrice) {
this.stockPrice = stockPrice;
stockPriceChanged();
}
public void stockPriceChanged() {
setChanged();
notifyObservers();
}
public String getStockSymbol() {
return stockSymbol;
}
public float getStockPrice() {
return stockPrice;
}
}
import java.util.Observable;
import java.util.Observer;
public class StockDisplay implements Observer {
private Observable stockData;
private String stockSymbol;
private float stockPrice;
public StockDisplay(Observable stockData) {
this.stockData = stockData;
stockData.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof StockData) {
StockData stockData = (StockData) o;
this.stockSymbol = stockData.getStockSymbol();
this.stockPrice = stockData.getStockPrice();
display();
}
}
public void display() {
System.out.println("Stock: " + stockSymbol + " Price: " + stockPrice);
}
}
public class StockController {
private StockData stockData;
public StockController(StockData stockData) {
this.stockData = stockData;
}
public void updateStockPrice(float newPrice) {
stockData.setStockPrice(newPrice);
}
}
public class StockMarket {
public static void main(String[] args) {
StockData stockData = new StockData("AAPL");
StockDisplay stockDisplay = new StockDisplay(stockData);
StockController stockController = new StockController(stockData);
stockController.updateStockPrice(150.0f);
stockController.updateStockPrice(155.0f);
}
}