本文参考HeadFirst
观察者模式定义了对象之间的一对多的依赖,当一个对象改变状态的时候,所有依赖它的对象都会接到通知并且进行更新。
我们以一个例子来说明,观察者与可观察者之间的关系以及其实现。
假如我们能从气象站拿到温度、湿度、气压的数据,我们要根据这三个数据展示一些看板,展示的看板必须依赖这些数据。
1.展示当前状况的看板,展示温度、湿度、气压。
2.展示其它的看板。
接下来我们就开始分析如何拆分个需求:
1.我们有一个WeatherData对象用来保存从气象站拿到的数据。
2.所有的看板都有同样的方法,需要更新看板数据以及展示数据,抽象出一个接口。
3.看板是依赖于WeatheData对象状态的变化,那么WeatherData则可以定义为主题(Subject)的实现。
4.所有的看板则为观察者。
根据以上的分析,那我们就可以初步的将类的结构定义出来了:
类图定义好了,我们就可以实现具体的代码了
主题:
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notfiyObserver();
}
主题实现:
import java.util.ArrayList;
import java.util.List;
/**
* 可观察者对象
*/
public class WeatherData implements Subject{
//温度
private float temp;
//湿度
private float humidity;
//气压
private float perssure;
private List<Observer> observerList;
public WeatherData() {
observerList = new ArrayList<>();
}
/**
* 注册观察者
* @param observer
*/
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
/**
* 删除观察者
* @param observer
*/
@Override
public void removeObserver(Observer observer) {
int index = observerList.indexOf(observer);
if(index > 0){
observerList.remove(index);
}
}
/**
* 通知观察者
*/
@Override
public void notfiyObserver() {
for(Observer observer:observerList){
observer.update(temp,humidity,perssure);
}
}
/**
* 模拟状态发生变化
* @param temp
* @param humidity
* @param perssure
*/
public void setMeasurments(float temp,float humidity,float perssure){
this.temp = temp;
this.humidity = humidity;
this.perssure = perssure;
notfiyObserver();
}
}
观察者
public interface Observer {
void update(float temp,float humidity,float perssure);
}
观察者实现
public class CurrentConditionsPanle implements Observer{
//温度
private float temp;
//湿度
private float humidity;
//气压
private float perssure;
public CurrentConditionsPanle(Subject weatherData) {
weatherData.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float perssure) {
this.temp = temp;
this.humidity = humidity;
this.perssure = perssure;
display();
}
public void display(){
System.out.println("温度:"+temp+","+"湿度:"+humidity+","+"气压:"+perssure);
}
}
测试类
public class Test {
public static void main(String[] args){
WeatherData weatherData = new WeatherData();
CurrentConditionsPanle currentConditionsPanle = new CurrentConditionsPanle(weatherData);
weatherData.setMeasurments(30.3f,25.2f,25.2f);
}
}