概念:当被观察者中的数据发生改变时,观察者这边会立即收到变化以后的数据。
观察者模式角色:1)主题 (被观察者-Subject) 2)观察者-Observer
所需接口:1)主题接口-ISubject 2)观察者接口-IObserver 3)展示接口-IDisplay
主题和观察者之间是如何进行关联的 :1)主题 implements ISubject 接口 ,观察者 implements IObserver ,IDisplay 接口
2) Obsever类中会将ISubject,当作自己的成员属性,通过构造器来与具体的Subject进行关联,让后Subject通过Register();对Observer进行注册。
3) 每一个具体的Subject实现类在实例化时,会new一个list集合用于承装注册过的Observer
4)当Subject中的数据发生改变时,会自动调用Notify(); Notify会自动调用Observer中的update();进行数据的更新操作,update会自动调用display();进行展示。
public interface ISubject {
/*
* 主题模板中有1:注册观察者 2:删除观察者 3:通知观察者 的方法*/
public void registerObserver(IObserver observer);
public void removeObserver(IObserver observer);
public void notifyObserver();
}
public interface IObserver {
/*观察者模板中有一个自动接收更新数据的方法*/
public void update(float temp,float humidity,float pressure);
}
public interface IDisplayElement {
/*
* 此方法用于布告板的显示跟新的数据*/
public void display();
}
/*具体的Subject实现类*/
public class WeatherData implements ISubject{
private ArrayList observerList;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
this.observerList = new ArrayList();
this.temperature = 35;
this.humidity = 85;
this.pressure = 120;
}
@Override
public void registerObserver(IObserver observer) {
observerList.add(observer);
}
@Override
public void removeObserver(IObserver observer) {
if(observerList.size() > 0) {
observerList.remove(observer);
}
}
@Override
public void notifyObserver() {
for(int i=0;i<observerList.size();i++) {
IObserver observer = (IObserver) observerList.get(i);
observer.update(temperature, humidity, pressure);
}
}
//调用该方法用来通知观察者,数据已经改变了
public void measurementsChanged() {
notifyObserver();
}
/*具体的Observer实现类*/
public void setMeasurements(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
public class SimpleDisplayElement implements IDisplayElement,IObserver {
private float tempreasure;
private float humidity;
//private float pressure;
/*与主题类相关联*/
private ISubject subject;
public SimpleDisplayElement(ISubject weatherData) {
this.subject = weatherData;
weatherData.registerObserver(this);//将当前的模板对象注册到该主题中
}
@Override
public void display() {
System.out.println("simple当前温度: "+ tempreasure);
System.out.println("simple当前湿度: "+ humidity);
// System.out.println("当前气压: "+ pressure);
}
@Override
public void update(float temp, float humidity, float pressure) {
this.tempreasure = temp;
this.humidity = humidity;
// this.pressure = pressure;
display();
}
}
public class ObserverPatternTest {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
SimpleDisplayElement display = new SimpleDisplayElement(weatherData);
HumidityDisplayElement humidity = new HumidityDisplayElement(weatherData);
weatherData.setMeasurements(10, 50, 40);
}
}
观察者模式(JDK内置实现)
原理:1)一个基类(Observable)2)一个Observer接口
2) 主题Subject需要 extends Observable类,观察者需要 implements Observer接口
3)Observable类中有一个boolean类型的change变量,只有当change = true时,才可以进行对Observer的数据的更新操作。
4)Observable中有两个notifyObserver的方法:1)notifyObserver(Object args) , 2)notifyObserver()--->内部调用的还是带参数的方法。
(1)调用带参数的方法证明观察者更新数据的方法是主题主动推送
(2) 调用不带参数的方法证明观察者更新数据的方法是 Observer主动拉取
5):4)中的notifyObserver();内部循环遍历数组,让后调用Observer实例中的update();该方法需要实例自己实现。
原生观察者模式与JDK内置实现的对比
因为java为单继承,所以当使用jdk内置实现时,就无法继承其他类,降低了程序的扩展性