观察者模式(Observable实体类 Observer接口)Java内置实现理解和使用
Java内置的观察者模式,是通过继承父类,实现观察者模式的几个主要函数:
Observable(可被观察的):是一个父类(class),内部已经实现了注册观察者:addObservar(),删除观察者:deleteObserver()等方法,通知观察者:notifyObservers();setChanged()用来标记主题的状态(可观察者),如果状态改变,将通知观察者
Oberver(观察者):是一个inferface(接口),实现update()方法,更改观察者数据,业务实现可在update()方法中去实现
主题(可观察者):主要流程 setChanged->notifyObservers(),要先调用setChanged()方法,再使用notifyObservers()方法,可以理解为先确认再提交,其实也是调用setChanged方法,主要是用来标记可观察者状态,下一步进行通知观察者。
观察者:更新接口update(Observerable obs,Object args)方法,即可以使用推(push)或者拉(pull)方式,拉的方式即使用get方法来获取。
观察者的通知(notify)顺序是先入后出的模式
可观察者到观察者的主要流转是这个样子的:可观察者调用setChanged()方法,来进行标记状态,表明主题发生改变,然后调用notifyObservers()方法,调用这个方法后,因为观察者实现了Observer接口,有update(Observerable obs,Object args)方法,会直接调用update(Observableobs,Object args)方法,就是说在update方法中,进行实现业务的过程中,先判断arg是否为null,来进行业务实现,如果args为null,则采用pull方式,如果不为null,则采用push的方式,获取数据就可以进行业务实现,不同的观察者可以订阅同一个可观察者(个人理解,可能会有偏差,如果疑问,可以进行评论,再次进行改进)
下面代码展示一下,看下效果:
/**
* Created on 2019/3/31.
* Title: Simple
* Description:可观察者
* Copyright: Copyright(c) 2019
*
*
* @author wy
*/
public class CityObservable extends Observable {
private float temperature;
private float humidity;
private float pressure;
public CityObservable() {}
public void measurementsChanged() {
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
/**
* Created on 2019/3/31.
* Title: Simple
* Description:观察者(并进行一些项目描述,应该如何去实现业务)
* Copyright: Copyright(c) 2019
* Company:
*
* @author wy
*/
public class CurrentConditionsDisplay implements Observer ,DisplayInterface {
Observable observable;
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("Current conditions: " + temperature +
"F degrees and " + humidity + "% humidity");
}
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if (o instanceof CityObservable) {
//TODO 可以进行业务实现
if (null==arg){
CityObservable weatherData = (CityObservable) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}else {
//TODO 声明
//采用推的方式,直接获取参数即可,如果知道可观察者的通知方法,就可以知道采用什么方式,
//在此,因为我们知道可观察者的调用方法,所以直接可以采用pull的方式来获取
}
}
}
/**
* Created on 2019/3/31.
* Title: Simple
* Description:观察者
* Copyright: Copyright(c) 2019
*
*
* @author wy
*/
public class ForecastDisplay implements Observer,DisplayInterface{
Observable observable;
private float temperature;
private float humidity;
public ForecastDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("ForecastDisplay: " + temperature +
"F degrees and " + humidity + "% humidity");
}
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if (o instanceof CityObservable) {
CityObservable weatherData = (CityObservable) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
/**
* Created on 2019/3/31.
* Title: Simple
* Description:接口
* Copyright: Copyright(c) 2019
*
*
* @author wy
*/
public interface DisplayInterface {
public void display();
}
/**
* Created on 2019/3/31.
* Title: Simple
* Description:测试类
* Copyright: Copyright(c) 2019
*
* @author wy
*/
public class Test {
public static void main(String[] args) {
CityObservable cityObservable = new CityObservable();
CurrentConditionsDisplay currentConditions = new CurrentConditionsDisplay(cityObservable);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(cityObservable);
cityObservable.setMeasurements(82, 70, 29.2f);
cityObservable.setMeasurements(78, 90, 29.2f);
}
}
由结果可见先进后出
我们在项目开发时不能依赖于被通知的次序:
Java.util.Observable实现了它的notifyObservers()方法,这导致了通知观察者的次序就不是有序的顺序,但是由上例所示,如果我们依赖于观察者获取数据的顺序就是错误的。
因为一旦观察者或者可观察者的实现有所改变,通知的次序可能就会改变,很可能会产生错误的结果,所以说在项目实现时不能依赖于观察者获取数据的顺序来进行实现,这绝对不是我们所认为的松耦合。(有些是个人理解的成分在内,如果不同的理解,可以评论,大家共同进步)