1.观察者模式是什么?
Java的观察者模式是一种设计模式,它属于行为型设计模式家族,用于处理软件系统中对象之间的联动或者说事件通知机制。在观察者模式中,存在两个核心角色:观察者(Observer)和被观察者(Observable)。这种模式定义了对象之间的一对多依赖关系,允许一个对象(被观察者)的状态变化自动通知其他对象(观察者),从而这些对象可以做出相应的行为。
以前记得都是自己写观察者注册、被观察者通知等操作,现在jdk将被观察者抽象出来了,只需要在业务变化中,调用抽象类的通知方法和数据已改变标识即可,观察者实现update方法即可。
2.观察者的实现
具体到Java语言中的实现:
抽象被观察者(Observable):
- Java提供了内置的
java.util.Observable
类作为抽象被观察者角色,它维护了一个观察者列表,并提供了添加、删除观察者以及通知所有观察者的方法。
- Java提供了内置的
具体被观察者(Concrete Observable):
- 这是一个继承自
Observable
的类,通常会包含一些业务逻辑,当其内部状态发生变化时,调用setChanged()
方法标记状态已更改,并通过调用notifyObservers(Object arg)
来通知所有注册的观察者。
- 这是一个继承自
抽象观察者(Observer):
- Java定义了
java.util.Observer
接口作为抽象观察者角色,接口中定义了update(Observable o, Object arg)
方法,这是观察者接收到通知时需要实现的更新逻辑。
- Java定义了
具体观察者(ConcreteObserver):
- 实现了
Observer
接口的类,它们关注并响应被观察者的特定状态变化。当被观察者调用notifyObservers()
时,所有具体观察者的update()
方法会被调用,此时观察者可以根据传递的信息更新自己的状态。
- 实现了
这样设计的好处在于降低了对象之间的耦合度,使得系统更易于扩展和维护,同时能够实现实时的数据同步和状态更新。在GUI编程、事件驱动框架、MVC架构等场景中,观察者模式得到了广泛的应用。
3.代码示例
示例代码以天气数据为例,各个不同功能的观察者根据天气数据做出不同的反应,天气数据改变后,通知观察者。
被观察者实现:
/**
* 被观察者,天气
*/
public class WeatherData extends java.util.Observable {
/**
* 温度
*/
private float temperature;
/**
* 湿度
*/
private float humidity;
/**
* 大气压
*/
private float pressure;
/**
* 设置业务数据,并通知观察者
* @param temperature
* @param humidity
* @param pressure
*/
public void setData(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
this.setChanged();
this.notifyObservers();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
观察者1的示例:
import com.zhangzz.WeatherData;
import java.util.Observable;
import java.util.Observer;
/**
* 气温观察者
*/
public class TemperatureObServer implements Observer{
/**
* 温度
*/
private float temperature;
/**
* 湿度
*/
private float humidity;
public void display() {
System.out.println("当前温度:" + temperature + "°C, 湿度:" + humidity + "%");
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof WeatherData){
WeatherData data = (WeatherData)o;
this.humidity = data.getHumidity();
this.temperature = data.getTemperature();
display();
}
}
}
观察者2的示例:
import com.zhangzz.WeatherData;
import java.util.Observable;
import java.util.Observer;
/**
* 具体观察者2:预报数据显示
*/
public class ForecastObServer implements Observer{
/**
* 大气压
*/
private float currentPressure = 29.92f; // 假设初始气压值
@Override
public void update(Observable o, Object arg) {
//通过该方式,可以观察多个被观察者,实现一对多的依赖。
if(o instanceof WeatherData){
WeatherData weatherData = (WeatherData) o;
float newPressure = weatherData.getPressure();
if (newPressure > currentPressure) {
System.out.println("明天可能是晴天");
} else if (newPressure < currentPressure) {
System.out.println("明天可能会下雨");
} else {
System.out.println("天气稳定");
}
currentPressure = newPressure;
}
}
}
测试代码:
import com.zhangzz.observer.ForecastObServer;
import com.zhangzz.observer.TemperatureObServer;
public class Test {
public static void main(String[] args) {
//实例化天气
WeatherData data = new WeatherData();
//实例化预报实例
ForecastObServer forecastObServer = new ForecastObServer();
//实例化气温实例
TemperatureObServer temperatureObServer = new TemperatureObServer();
//像被观察者注册实例
data.addObserver(forecastObServer);
data.addObserver(temperatureObServer);
//修改气温数据
data.setData(80, 65, 30.4f);
data.setData(82, 70, 29.2f);
}
}
执行结果:
当前温度:80.0°C, 湿度:65.0%
明天可能是晴天
当前温度:82.0°C, 湿度:70.0%
明天可能会下雨
良好的代码设计,可以为系统带来更大的成长空间。避免了屎山代码导致系统无法继续迭代升级的可能。