前言
我们在Android ListView或者Recyclerview的开发中,常常是数据更新之后要立刻去更新界面,这种Adapter的notifyDateSetChanged就运用了观察者模式;观察者模式是一种使用率非常高的模式,常常用到GUI之类的的系统中,界面跟随数据发生改变,使得UI和具体的页面逻辑分开解耦,换而言之,观察者模式就是一对多的关系,一个对象发生改变,其依赖于它的所有对象都收到通知,更新对象本身。
适用场景
1,事件多级触发场景,一对多关系的一种体现。
2,事件总线场景,这个最多使用的是EventBus。
角色扮演
Subject:被观察者的抽象类,一般提供接口满足添加和删除观察者对象。
ConcreteSubject:具体的被观察者,实现Subject的接口。
Observer:抽象观察者,就是观察者的抽象类,定义更新接口来更新自己的数据。
ConcreteObserver:具体观察者,实现更新自身数据的方法。
观察者模式的简单实现
简单抽象一个demo,我的桌子上有一个电子温度计,其功能就是显示室内温度跟湿度,那么我们抽象的过程就是,当温控原件检测到温度和湿度发生变化时,通知界面刷新,首先我们申明抽象被观察者:
package com.demo.observable;
/**
* Created by italkbb on 2017/12/25.
*/
/**
* 被观察者的接口
*/
public interface Subject {
/**
* 注册观察者
*/
void registerObserver(Observer observer);
/**
* 移除观察者
*/
void deleteObservers();
/**
* 通知观察者
*/
void notifyObservers();
}
下面实现这个被观察者:
package com.demo.observable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by italkbb on 2017/12/25.
*/
public class WeatherSubject implements Subject {
// 观察者
private List<Observer> mObservers;
// 信息
private float mTemperature;//温度
private float mHumidity;//湿度
public WeatherSubject(){
this.mObservers = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer observer) {
this.mObservers.add(observer);
}
@Override
public void deleteObservers() {
this.mObservers.clear();
}
@Override
public void notifyObservers() {
for (Observer observer : mObservers) {
observer.updateInfo();
}
}
public void setWeatherInfo(float temperature, float humidity) {
this.mTemperature = temperature;
this.mHumidity = humidity;
// 信息更新完毕了,通知观察者
notifyObservers();
}
/**
* 得到测量温度
* @return
*/
public float getTemperature() {
return mTemperature;
}
/**
* 得到测量湿度
* @return
*/
public float getHumidity() {
return mHumidity;
}
}
上面的类基本满足了设备信息改变通知观察者的功能,下面同样来写观察者:
package com.demo.observable;
/**
* Created by italkbb on 2017/12/25.
*/
/**
* 观察者接口
*/
public interface Observer {
void updateInfo();
}
实现它:
package com.demo.observable;
/**
* Created by italkbb on 2017/12/25.
*/
public class WeatherInfoDisplay implements Observer {
private WeatherSubject mWeatherSubject;
private float mTemperature;//温度
private float mHumidity;//湿度
public WeatherInfoDisplay(WeatherSubject weatherSubject){
this.mWeatherSubject = weatherSubject;
this.mWeatherSubject.registerObserver(this);
}
public void display() {
// 简单抽象显示为java的打印语句
System.out.println("温度:" + this.mTemperature + "℃");
System.out.println("湿度:" + this.mHumidity);
}
@Override
public void updateInfo() {
this.mTemperature = this.mWeatherSubject.getTemperature();
this.mHumidity = this.mWeatherSubject.getHumidity();
display();
}
}
接下来就简单使用一下:
package com.demo.observable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import teltplay.example.com.kotlindemo.R;
public class WeatherActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather);
WeatherSubject mWeatherSubject = new WeatherSubject();
WeatherInfoDisplay mWeatherInfoDisplay = new WeatherInfoDisplay(mWeatherSubject);
mWeatherSubject.setWeatherInfo(1.0f,0.36f);
}
}
就这样一个简单的观察者模式就完成了,当然要实现复杂的逻辑,也就大同小异了。
后记
优点缺点说一下,优点嘛,观察者与被观察者低耦合,也就增加了代码的扩展性;缺点就是如果简单的采取循环通知观察者,可能会由于顺序执行的关系卡住线程,但这个用多线程就会解决,但同时带来的就是效率问题了,太多的观察者,在多线程,资源消耗值得考虑。