参考文档:
http://www.jianshu.com/p/d55ee6e83d66
文章中的例子来源于参考文献,更详细的讲解在参考文章中,本文是自己的一个理解
观察者模式使用场景:
A对象(观察者)对B对象(被观察者)的某种变化高度敏感,需要在B变化的一瞬间做出反应。在代码上实现上,通常是被观察者主动去注册或者订阅一个观察者,
构建观察者模式
1.被观察者持有观察者对象,这一步骤通常是通过被观察者注册(Register方法)或者订阅(Subscribe方法)观察者实现的。
2.观察者同样持有被观察者对象,同时调用被观察者的订阅方法完成订阅。(被观察者拿到观察者对象这一步通常在观察者类中去做。)
3.被观察者具有一个"通知观察者的"方法,该方法通过调用被观察者内部持有的观察者对象的方法来达到通知观察者的目的。
(其实所谓收到通知就是被观察者做某些操作时,同时调用了观察者的特定方法。)
实现过程
被观察者接口
/** * 主题(发布者、被观察者) */
public interface Subject {
/** * 注册观察者 */
void registerObserver(Observer observer);
/** * 移除观察者 */
void removeObserver(Observer observer);
/** * 通知观察者 */
void notifyObservers(); }
观察者接口
/** * 观察者 */
public interface Observer {
void update();
}
具体实现
被观察者:
1.被观察者持有观察者对象。
2.被观察者持有的观察者对象通过订阅(注册方法拿到)
3.被观察者数据改变的时候通知观察者(通过调用观察者的update方法)
public class WeatherData implements Subject {
private List<Observer> observers;//1.被观察者持有观察者对象。
private float temperature;
private float humidity;
private float pressure;
private List<Float> forecastTemperatures;
//未来几天的温度
public WeatherData() { this.observers = new ArrayList<Observer>();
//被观察者持有的观察者对象通过订阅
@Override
public void registerObserver(Observer observer) { this.observers.add(observer); }
@Override
public void removeObserver(Observer observer) {
this.observers.remove(observer);
}
通知观察者
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
在数据更新的时候通知观察者
public void changeWeatherData(float temperature, float humidity, float pressure, List<Float> forecastTemperatures) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
this.forecastTemperatures = forecastTemperatures;
notifyObservers();
}
public float getTemperature() { return temperature; }
public float getHumidity() { return humidity; }
public float getPressure() { return pressure; }
public List<Float> getForecastTemperatures() { return forecastTemperatures; }}
观察者:
1.观察者持有被观察者对象(WeatherData)
2.将自身传递给被观察者(使用被观察者的注册方法)
3.提供一个方法,负责在被观察者改变的时候刷新自身。(持有update方法,update方法实际做事情,该方法在被观察者中被调用)
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private WeatherData weatherData; //持有被观察者对象
private float temperature;
private float humidity;
private float pressure;
public CurrentConditionsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
this.weatherData.registerObserver(this);//被观察者对象拿到观察者
}
@Override
public void display() {
System.out.println("当前温度为:" + this.temperature + "℃");
System.out.println("当前湿度为:" + this.humidity);
System.out.println("当前气压为:" + this.pressure); }
@Override
public void update() {
//数据都是通过被观察者拿到的
this.temperature = this.weatherData.getTemperature();
this.humidity = this.weatherData.getHumidity();
this.pressure = this.weatherData.getPressure();
display();
}
}
使用例子:
//被观察者
WeatherData weatherData = new WeatherData();
//观察者
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
//被观察者数据改变
List<Float> forecastTemperatures = new ArrayList<Float>();
forecastTemperatures.add(22f);
forecastTemperatures.add(-1f);
forecastTemperatures.add(9f);
weatherData.changeWeatherData(22f, 0.8f, 1.2f, forecastTemperatures);
//被观察者数据改变的时候(即调用changeWeatherData时,实际上内部调用了观察者的update方法,主动通知观察者)
笔者使用实例:
场景:在RecycleView中需要一个测试每一个展示出来的ip的延时,并且展示在Recycleview上。延时的展示和其他数据的展示是不同步的。测量延时采用的策略是 ping 地址5秒后拿到一个结果。所以采用观察者模式,当获取到延时数据(即数据改变的时候)更新UI。
被观察者RobotBean对象
1.持有观察者对象:registerOberver方法
2.被观察者改变的时候通知观察者:notifyIpChange方法
观察者ViewHolder对象
1.持有被观察对象
2.传递观察者:
3.提供一个更新方法