今天我们讲一下设计模式之观察者模式,话不多说,首先我们以天气预报来讲一个例子吧。
天气预报大家都知道,我需要对天气进行实时的监听,这个时候我们把这个天气状况当成一个对象来说,有可能这个对象的状态会发生改变,这个时候我们需要对其他的对象也做相应的改变。
那么我们举一个例子来说,比如我们把天气预报当成一个被观察者,我们需要一个管理观察者的接口和一个天气预报观察者的接口,这里我直接贴代码看
//天气预报观察者里有两个方法 一个更新数据 一个显示数据
public interface WeatherForecastObserver {
//更新数据
public abstract void updateData(String weather, String windDirection, int temperature, int humidity);
//显示数据
public abstract void displayData();
}
这是管理观察者的接口
//这是管理天气预报观察者的
public interface WeatherObserverManager {
//可以添加天气预报观察者
public abstract void addObserver(WeatherForecastObserver mfo);
//可以移除天气预报观察者
public abstract void removeObservers(WeatherForecastObserver mfo);
//也可以通知天气预报观察者更新
public abstract void notification(String weather,
String windDirection,
int temperature,
int humidity);
}
这样的话我们就可以实时的去改变它的数据及时更新通知。。
然后呢我们写一个管理观察者的类去实现这个接口,,类里面有存放这个观察者的集合方便我们添加更多的观察者
//这是一个管理观察者的类 实现了这个管理天气预报观察者的接口类
public class ObserverManagers implements WeatherObserverManager {
//天气
private String weather;
//风向
private String windDirection;
//温度
private int temperature;
//湿度
private int humidity;
private ArrayList<WeatherForecastObserver> list;
public ObserverManagers() {
list=new ArrayList<WeatherForecastObserver>();
}
public int getHumidity() {
return humidity;
}
public int getTemperature() {
return temperature;
}
public String getWeather() {
return weather;
}
public String getWindDirection() {
return windDirection;
}
@Override
public void addObserver(WeatherForecastObserver mfo) {
list.add(mfo);
}
@Override
public void removeObservers(WeatherForecastObserver mfo) {
if (list.contains(mfo)){
list.remove(mfo);
}
}
@Override
public void notification(String weather, String windDirection, int temperature, int humidity) {
for (WeatherForecastObserver wf:list){
wf.updateData(weather, windDirection, temperature, humidity);
}
}
}
这个时候架子算搭好了,,我们引用两个观察者来,比如我们引用一个QQ天气预报和一个北京天气预报
//实现这个天气预报的观察者
public class QQWeather implements WeatherForecastObserver {
private int temperature;
@Override
public void updateData(String weather, String windDirection, int temperature, int humidity) {
this.temperature=temperature;
displayData();
}
@Override
public void displayData() {
System.out.println("qq天气预报:今日温度"+temperature);
}
}
public class BeiJingWeather implements WeatherForecastObserver {
//天气
private String weather;
//风向
private String windDirection;
//温度
private int temperature;
//湿度
private int humidity;
@Override
public void updateData(String weather, String windDirection, int temperature, int humidity) {
this.humidity = humidity;
this.temperature = temperature;
this.weather = weather;
this.windDirection = windDirection;
displayData();
}
@Override
public void displayData() {
System.out.println("这里是北京台气象预报,今天的湿度是" + humidity +
",温度是" + temperature + ",天气是" + weather + ",风向是" + windDirection);
}
}
为了区分开,我们只给QQ天气预报一个参数。
最后我们在Mainctivity中,去实现一下
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BeiJingWeather beiJingWeather=new BeiJingWeather();
QQWeather qqWeather=new QQWeather();
ObserverManagers observerManagers=new ObserverManagers();
observerManagers.addObserver(beiJingWeather);
observerManagers.addObserver(qqWeather);
observerManagers.notification("阴天","下大雨",20,10);
observerManagers.removeObservers(qqWeather);
observerManagers.addObserver(qqWeather);
observerManagers.notification("雾霾","小雨",10,20);
}
}
这个时候我们可以看一下打印日志
I/System.out: 这里是北京台气象预报,今天的湿度是10,温度是20,天气是阴天,风向是下大雨
I/System.out: 这里是北京台气象预报,今天的湿度是20,温度是10,天气是雾霾,风向是小雨
I/System.out: qq天气预报:今日温度10
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 10-13 09:24:31.794 5502: 5502 D/ ]
HostConnection::get() New Host Connection established 0xab2fc010, tid 5502
[ 10-13 09:24:31.842 5502: 5518 D/ ]
HostConnection::get() New Host Connection established 0xab2fc160, tid 5518
I/OpenGLRenderer: Initialized EGL, version 1.4
走一下逻辑,第一次我们添加了北京天气预报打印一次,然而第二次我们并没有移除北京天气预报,所以第二次通知更新的时候,北京天气预报也跟着更新了,而且数据也发生了变化,,然后我们把天气预报在第二次的时候移除一下。。在看一下打印日志,,大家猜一下会打印什么呢·····
$ adb shell am start -n "xi.observermodule/xi.observermodule.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 5620 on device Nexus_4_API_23 [emulator-5554]
W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
I/System.out: 这里是北京台气象预报,今天的湿度是10,温度是20,天气是阴天,风向是下大雨
I/System.out: qq天气预报:今日温度10
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
I/OpenGLRenderer: Initialized EGL, version 1.4
看是不是只有一条北京预报的,,因为我们移除了北京天气预报,但我们发现北京预报的数据还是第一次更新的,,因为我们第二次与北京天气预报没有合作了,所以我们不给他提供更新服务了,如果我们和多个气象台合作的话,,我们可以实时的通知各个气象台更新天气数据。如果不想通知某个也可以,,也就是不合作了,,这就是观察者模式,它会监听你的状态,,然后实时的去通知你更新数据,同样一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其他的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作。观察者模式是满足这一要求的各种设计方案中最重要的一种。