一、何为观察者模式
何谓观察者模式?观察者设计模式是一种行为型设计模式,观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象的状态发生变化时,它的所有依赖对象都会收到通知并自动更新。
观察者模式的关键点:对象间的一对多的依赖关系
二、观察者模式设计
在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以可以根据需要增加和删除观察者,使得系统更易于扩展。所以观察者提供了一种对象设计,让主题和观察者之间以松耦合的方式结合。
观察者模式包含如下角色:
- Subject: 目标
- ConcreteSubject: 具体目标
- Observer: 观察者
- ConcreteObserver: 具体观察者
我们使用气象站主题对象和当前天气显示观察者对象之间的交互过程。当气象站采集到新的数据时,它会通知所有观察者并更新它们的状态。在此示例中,当前天气显示观察者将显示气象站采集到的当前温度和湿度。
三、代码实现
1.目标接口
public interface Subject {
/**
* 注册观察者
* @param observer
*/
void registerObserver(Observer observer);
/**
* 移除观察者
* @param observer
*/
void removeObserver(Observer observer);
/**
* 通知所有观察者
*/
void notifyObservers();
}
2.观察者接口
public interface Observer {
/**
* 更新观察者状态
* @param temperature
* @param humidity
* @param pressure
*/
void update(float temperature, float humidity, float pressure);
}
3.具体目标
所有观察者注册到目标对象,目标对象拥有多个观察者,是一种聚合关系
public class WeatherData implements Subject {
/**
* 观察者列表(关键点)
*/
private List<Observer> observers;
/**
* 温度
*/
private float temperature;
/**
* 湿度
*/
private float humidity;
/**
* 气压
*/
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
/**
* 注册观察者
* @param observer
*/
public void registerObserver(Observer observer) {
observers.add(observer);
}
/**
* 移除观察者
* @param observer
*/
public void removeObserver(Observer observer) {
observers.remove(observer);
}
/**
* 通知所有观察者
*/
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
/**
* 当气象站测量到新的数据时,就调用此方法
*/
public void measurementsChanged() {
notifyObservers();
}
/**
* 设置气象站采集到的数据
* @param temperature
* @param humidity
* @param pressure
*/
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
4.具体观察者
public class CurrentConditionsDisplay implements Observer{
/**
* 温度
*/
private float temperature;
/**
* 湿度
*/
private float humidity;
/**
* 气压
*/
private float pressure;
@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("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
5.测试
public class ObserverTest {
public static void main(String[] args) {
// 创建主题对象
WeatherData weatherData = new WeatherData();
// 创建观察者对象
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
// 注册观察者
weatherData.registerObserver(currentDisplay);
// 设置气象站采集到的数据
weatherData.setMeasurements(80, 65, 30.4f);
}
}
四、应用案例
可以查阅我的另一篇博文Spring事件机制