什么是观察者模式
我个人的理解是,观察者模式就是一个主题,多个观察者,就好比我们常常用的微信公众号,是不是一个公众号下面关注了很多的人?然后呢公众号有什么推送的时候,他会给所有关注他的人推送这些消息,而这些关注的用户又可以选择不关注(可能觉得没意思了)
UML类图如下
代码理解(书中的气象站例子)
1.编写主题
2.编写观察者
3.单独写一个显示数据的方法(这个可有可无的,只是为了测试效果)
4.具体的主题
/**
* ClassName:WeatherData
* Author:LFM
* Date:2019/8/11 16:43
**/
public class WeatherData implements Subject {
private ArrayList observers;//考虑多个观察者会关注一个主题的
//定义状态变量
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers = new ArrayList();//在构造器完成初始化
}
@Override
public void registerObeserver(Obeserver obeserver) {
observers.add(obeserver);//注册方法,只需添加到集合里面即可
}
@Override
public void removeObeserver(Obeserver obeserver) {
int i = observers.indexOf(obeserver);//移除方法,得到要移除观察者的下标值
if (i>=0){
observers.remove(i);
}
}
//通过这个方法手动设置一些气象数据,然后调用状态改变方法
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//这个状态改变方法再调用通知方法
public void measurementsChanged(){
notifyObeservers();
}
@Override
public void notifyObeservers() {
//通过循环的方式通知每一个观察者
for (int i=0;i<observers.size();i++){
Obeserver obeserver = (Obeserver)observers.get(i);
obeserver.update(temperature,humidity,pressure);
}
}
}
5.具体观察者
6.写个测试类
7.结果
还有一种就是继承Observerble类,这是JDK内置的观察者模式
1.我们不需要自己定义主题了,继承这个类就行了
记得导入相应的包
import java.util.Observable;
/**
* 使用JDK内置的观察者模式
* ClassName:WeatherData
* Author:LFM
* Date:2019/8/12 15:18
**/
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
//现在已经不需要在构造器里面保存观察者们了
public WeatherData(){
}
//这是手动设置数据的方法
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();//设置完数据就可以通知观察者了
}
public void measurementsChanged(){
setChanged();//这个是父类的方法,用来记录状态是否改变
notifyObservers();//这个是父类的方法,通知观察者
}
//以下三个getter方法是为了观察者手动拉数据而设立的
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
2.同样的也不需要自己写观察者接口了
这个DIsplayElement是我们用来显示数据的方法
import java.util.Observable;
import java.util.Observer;
/**
* ClassName:CurrentConditionsDisplay
* Author:LFM
* Date:2019/8/12 15:26
**/
public class CurrentConditionsDisplay implements Observer,DisplayElement {
Observable observable;//引入主题依赖
private float temperature;
private float humidity;
private float pressure;
public CurrentConditionsDisplay(Observable observable){
this.observable = observable;//初始化
observable.addObserver(this);//调用父类的方法登记观察者
}
/*现在这个方法是jDK内置的更新方法
前一个参数是确定具体的主题类型,后一个参数是主题
notifyObservers方法里面传递过来的参数,不写默认为空
*/
@Override
public void update(Observable o, Object arg) {
//确定观察者属于哪个主题,然后调用方法从该主题拉取数据
if (o instanceof WeatherData){
WeatherData weatherData = (WeatherData) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
this.pressure = weatherData.getPressure();
display();
}
}
@Override
public void display() {
System.out.println("Current conditions:"+
temperature+"F degree and "+humidity+"% humidity"+pressure+"pressure");
}
}
3.测试一下
4.结果
可以看出同样可以实现功能
总结,我们手动实现的观察者模式扩展性较好,JDK内置的较差,毕竟要继承不同的类,这就不符合多用组合,少用继承,面向接口编程了嘛