概念:
定义对象间的一种一对多的依赖关系
当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,本质是触发联动
结构:
1 目标对象的定义
2 具体的目标对象定义
3 观察者的接口定义
4 观察者的具体实现
触发时机:
是在完成状态维护后触发,因为通知会传递数据,不能先通知,后改数据,这会导致观察者和目标对象状态不一致
通知观察着的顺序是不一定的,观察者的实现,不能依赖于通知的顺序
多个观察者的顺序是平行的,相互不应该有先后以来的关系
推拉模型:
推模型:
目标对象主动向观察者推送目标的详细信息,推送的信息通畅是目标对象的全部or部分数据,相当于在广播通讯
拉模型:
目标对象在通知观察者的时候,值传递少量信息,如果观察者需要更具体的信息,由观察者主导到目标对象中获取,相当于是观察者从目标对象中拉数据,一版这种模型的实现中,会把目标对象通过update方法,传递给观察者
推模型 是假定目标对象知道观察者需要的数据,会使得观察者难以复用
拉模型是目标对象不知道观察者具体需要什么数据,因此只能把自身传递给观察者,拉模型基本适应各种情况的需要
可以区别对待观察者:
根据不同的状态进行不同的通知
代码实例:
/**
* 主题
*/
public interface Subject {
// 观察者注册
public void registerObserver(Observer o);
// 删除观察者
public void removeObserver(Observer o);
// 当主题有内容更新时调用,用于通知观察者
public void notifyObserver();
}
/**
* 用于布告板显示
*/
public interface DisplayElement {
// 在显示布告板上显示的操作
public void display();
}
/**
* 气象站实现主题,发布气象信息(气温)
*/
public class WeatherStation implements Subject{
private ArrayList observers;
private float temp;
public WeatherStation() {
// 加个ArrayList存放所有注册的Observer对象;
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer o) {
// 当新的观察者注册时添加进来
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
// 当观察者取消注册时去除该观察者
int i = observers.indexOf(o);
if (i>=0) {
observers.remove(i);
}
}
@Override
public void notifyObserver() {
// 更新状态,调用Observer的update告诉观察者有新的信息
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.update(temp);
}
}
/*
* 此方法用于气象站收到的数据,并且调用更新使数据实时通知给观察者
*/
public void setMeasurements(float temp){
this.temp = temp;
System.out.println("气象站测量的温度为:" + temp + "℃");
notifyObserver();
}
}
/**
* 布告板上的状态显示
*/
public class ConditionDisplay implements Observer,DisplayElement{
private float temp;
private Subject weatherStation;
public ConditionDisplay(Subject weatherStation) {
// 构造时需要间主题/被观察者对象作为注册之用
this.weatherStation = weatherStation;
weatherStation.registerObserver(this);
}
@Override
public void display() {
// 将数据显示在布告板上
System.out.println("布告板显示当前温度为:" + temp + "℃");
}
@Override
public void update(float temp) {
// 接受来自主题/被观察者(气象站)的数据
this.temp = temp;
display();
}
}