前言
观察者模式,即为观察对象的变化,并能够随时得到对象变化的通知。此类模式我们在平时开发中所见的也比较多,例如我们安卓开发中的Rxjava、EventBus等;
观察者模式
前言中说了。观察者模式即为观察对象的变化,并能够及时得到通知;接下来我们就引入一个例子进行循序渐进地进行分析一下。
现在假如我们手上有个某米的智能设备,此智能设备有个显示屏,同时装备有温度、湿度、气压感应装置。使得显示屏可以显示温度、湿度、气压的情况。

这里我们就需要显示被通过去观察智能设备的Weather对象,从而当Weather对象只要一变化,相应显示屏就应该去变化。
于是我们想到一种可以去实现的方式:
public class WeatherData {
public float getTemperature(){
return 0;
};
public float getHumidity(){
return 0;
};
public float getPressure(){
return 0;
};
public void measureChanged(){
float tem = getTemperature();
float hum = getHumidity();
float pre = getPressure();
//显示器显示
tmpDisPlay.show(tem);
humDisPlay.show(hum);
preDisPlay.show(pre);
}
我们可以看到这里通过WeatherData类的measureChanged方法对应去显示屏显示;
这样的做法也是能够实现,但是我们设计模式中有一个原则是:针对经常改变的地方,我们应该需要封装起来。而这里,温度,湿度,压力显然是会经常改变的,所有我们应该给封装起来;这里的这些智能检测到的气象数据显然是被观察者,而相应的温度、湿度、气压的显示屏显示则是观察者。在对整个设计进行更改之前我们先来看看观察者模式的类图:

这里我们的WeatherData相当于被观察者,而显示器则相当于观察者需要进行同步数据的显示:
public class WeatherData implements Subject {
private ArrayList <Observer> observers;
private float tem;
private float hum;
private float pre;
public WeatherData(){
observers = new ArrayList<Observer>();
}
public void registerObserver(Observer o){
observers.add(o);
}
public void removeObserver(Observer o){
int i = observers.indexOf(o);
if(i >= 0){
observers.remove(i);
}
}
public void notifyObserver(){
for(Observer o : observers){
o.update(tem,hum,pre);
}
}
public void measureChanged(){
notifyObserver();
}
public void setMeasureChangeData(float tem, float hum, float pre){
this.tem = tem;
this.hum = hum;
this.pre = pre;
measureChanged();
}
}
public class Display implements Observer{
private float tem;
private float hum;
private float pre;
public WeatherData weatherData;
public Display(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update( float tem, float hum, float pre){
this.tem = tem;
this.hum = hum;
this.pre = pre;
display();
}
public void display(){
System.out.print("tem="+tem+",hum="+hum+",pre="+pre);
}
}
这里我们就实现了针对此智能设备观察者和被观察者的设计,目前这里只有一个观察者Display,我们先来使用下这个智能设备。
public static void main(String [] args){
WeatherData weatherData = new WeatherData();
Display display = new Display(weatherData);
weatherData.setMeasureChangeData(1.0,2.0,3.0);
}
当weatherData数据变声了变化,则对应控制台则会打印出"tem=1.0,hum=2.0,pre=3.0,从而及时通知到了Display进行显示相关状态;
这里我们只有一个观察者Display,加入我们这个智能设置还有一个观察者HumDisplay;我们至于要根据湿度的情况来决定是否需要加湿器开启;
public class HumDisplay implements Observer{
private float tem;
private float hum;
private float pre;
public WeatherData weatherData;
public HumDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update( float tem, float hum, float pre){
this.tem = tem;
this.hum = hum;
this.pre = pre;
display();
}
public void display(){
if(hum < 5.0 && hum > 0){
System.out.print("开启加湿器");
}
}
}
public static void main(String [] args){
WeatherData weatherData = new WeatherData();
Display display = new Display(weatherData);
HumDisplay humDisplay = new HumDisplay(weatherData);
weatherData.setMeasureChangeData(1.0,2.0,3.0);
}
此时我们同样对humDisplay 进行了监听,当检测到weatherData的数据发生了变化,在控制台可以看到打印出“开启加湿器的信号”;
最后我们再看下整个观察者模式中使用到的类以及他们之间的联系:

网友评论