Java设计模式之观察者模式的示例分析
观察者模式是一种常用的设计模式,主要用于在对象间建立一种一对多的依赖关系,使得当一个对象状态改变时,所有依赖它的对象都能够得到通知并自动更新。通俗的说法就是,观察者模式是一种消息发布/订阅机制,当消息发布时,所有订阅这个消息的对象都会收到通知并作出相应的处理。
下面通过一个简单的示例来分析观察者模式。
假设有这样一个场景:有一个气象站,能够获取当前的温度、湿度、气压等信息,并将这些信息发送给不同的观察者对象,比如天气公告板、手机App、电视机等。同时,当气象站的信息发生变化时,所有的观察者对象都能够得到通知并更新自己的显示内容。
首先,我们需要定义一个气象数据的类,该类包含温度、湿度、气压等属性和相应的getter方法。此外,我们还需要在该类中定义一个方法,用于通知所有观察者对象数据发生了变化。具体代码如下:
public class WeatherData {
private float temperature; // 温度
private float humidity; // 湿度
private float pressure; // 气压
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
// 当气象数据发生变化时,通知所有观察者对象
public void measurementsChanged() {
// TODO: 通知所有观察者对象
}
}
接下来,我们需要定义一个观察者接口,该接口包含一个update()方法,在数据发生变化时会被调用。同时,为了将观察者对象注册到气象数据类中,我们还需要在该接口中定义一个register()方法和一个remove()方法。具体代码如下:
public interface Observer {
// 当数据发生变化时,会被调用
void update(float temperature, float humidity, float pressure);
// 将观察者对象注册到气象数据类中
void register(Subject subject);
// 将观察者对象从气象数据类中移除
void remove(Subject subject);
}
接着,我们需要定义一个具体的观察者类,该类实现了上述的Observer接口,具体实现了update()方法和register()/remove()方法。此外,我们还需要在该类中定义一个display()方法,用于显示观察者对象的内容。具体代码如下:
public class WeatherDisplay implements Observer {
// 定义观察者对象需要观察的气象数据对象
private Subject weatherData;
// 温度
private float temperature;
// 湿度
private float humidity;
// 气压
private float pressure;
public WeatherDisplay(Subject weatherData) {
this.weatherData = weatherData;
// 将当前观察者对象注册到气象数据对象中
weatherData.register(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
// 更新观察者对象的温度、湿度、气压
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
// 显示观察者对象的内容
display();
}
@Override
public void register(Subject subject) {
// 将当前观察者对象注册到指定的气象数据对象中
this.weatherData = subject;
subject.register(this);
}
@Override
public void remove(Subject subject) {
// 将当前观察者对象从指定的气象数据对象中移除
subject.remove(this);
}
public void display() {
// 显示观察者对象的内容
System.out.println("Temperature: " + temperature);
System.out.println("Humidity: " + humidity);
System.out.println("Pressure: " + pressure);
}
}
最后,我们需要在WeatherData类中完成measurementsChanged()方法的具体实现,即通知所有观察者对象数据发生了变化。具体代码如下:
public class WeatherData {
private float temperature; // 温度
private float humidity; // 湿度
private float pressure; // 气压
private List<Observer> observers; // 观察者对象列表
public WeatherData() {
observers = new ArrayList<>();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
// 当气象数据发生变化时,通知所有观察者对象
public void measurementsChanged() {
// 遍历所有观察者对象,调用它们的update()方法
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
// 注册观察者对象
public void registerObserver(Observer observer) {
observers.add(observer);
}
// 移除观察者对象
public void removeObserver(Observer observer) {
observers.remove(observer);
}
// 设置气象数据
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged(); // 数据发生变化,通知所有观察者对象
}
}
至此,以上代码就实现了观察者模式。具体实现过程如下:
1. 定义气象数据类WeatherData,包含温度、湿度、气压等属性。当数据发生变化时,调用measurementsChanged()方法通知所有观察者对象。
2. 定义观察者接口Observer,包含update()方法、register()方法和remove()方法。update()方法在数据发生变化时被调用,register()方法用于将观察者对象注册到指定的气象数据类中,remove()方法用于将观察者对象从指定的气象数据类中移除。
3. 定义具体的观察者类WeatherDisplay,实现了Observer接口。在构造函数中,将当前观察者对象注册到指定的气象数据类中。在update()方法中,更新观察者对象的温度、湿度、气压,并调用display()方法显示观察者对象的内容。
4. 在WeatherData类中,maintain一个观察者对象列表,实现registerObserver()方法、removeObserver()方法和measurementsChanged()方法。registerObserver()方法用于注册观察者对象,removeObserver()方法用于移除观察者对象,measurementsChanged()方法用于通知所有观察者对象数据发生变化。
总的来说,观察者模式是一种十分灵活的设计模式,它将依赖的行为分离出来,让高耦合变成松耦合,不同的观察者可以自由的增加、删除和更新,同时也大大增强了对象之间的交互性。对于使用场景中存在多个订阅者,需及时体现更新等操作时,观察者模式十分有效,它们也可以很好地协同工作,便于单元测试和复用。
