个人理解,如有错误,请大家指出,感谢!
1.什么是观察者模式?
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
比如说,我们要设计一个气象站的显示牌,当气温、湿度等改变了,就更新显示牌。一种做法是,所有显示牌轮询气象数据,当气象数据与上次轮询得到的数据不一致时,就更新显示牌,这是一种很糟糕的做法,浪费了我们的资源(至少浪费了CPU)。
那么观察者模式就可以很好地应用于这个例子,套到定义中是:显示牌作为依赖,当气象数据改变时,就通知显示牌,所有显示牌都会收到通知并自动更新显示。
我可以看到:
1.这种以通知代替轮询的做法大大节省了我们的资源。
2.这种做法实现了解耦,显示牌不再需要直接调用气象数据,而是在气象数据中维护了一组显示牌的引用,当气象数据发生改变时,循环调用显示牌的更新方法。
2.示例
UML图如下:
好了,我们开始写代码:
首先是我们的Subject接口:
public interface Subject {
void registerObserver(Observer o); //接口中的属性默认都是public的
void removeObserver(Observer o);
void notifyObserver();
}
Subject接口的实现类WeatherData:
import java.util.ArrayList;
public class WeatherData implements Subject {
private ArrayList<Observer> observers;
private float temp;
public WeatherData() {
this.observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update(temp);
}
}
public void measureChanged() {
notifyObserver();
}
public void setTemp(float temp) {
this.temp = temp;
measureChanged();
}
}
我们的Observer接口:
public interface Observer {
void update(float temp);
}
Display接口(这个接口的目的是:平时自己写代码玩一玩,也要规范一点):
public interface Display {
void display();
}
显示牌(实现了Observer接口和Display接口):
public class Board implements Observer, Display {
private float temp;
//有人可能会问,为什么要有这个引用?
//我们之后可以看到,有了这个引用,注册和取消注册会比较方便
private Subject weatherData;
public Board(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);//注册
}
@Override
public void display() {
System.out.println("temp: "+temp);
}
@Override
public void update(float temp) {
this.temp = temp;
display(); //温度改变,就会显示
}
}
大功告成!测试代码:
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
Board board = new Board(weatherData);
weatherData.setTemp(30);
}
}