模式定义
观察者模式(Observer) 定义了对象间的一对多依赖,当一个对象(Subject)状态改变时,所有的依赖者(Observer)都会收到通知并自动更新。
设计原则
松耦合设计。 双方不知道彼此具体是什么,只知道对方实现了某一接口。将对象间的依赖降到了最低。
问题场景
有一个气象站,存有采集到的气象数据。目前的工作为建立一个系统,利用气象站的数据更新三个布告板:目前状况、气象统计、天气预报。要求当气象数据更新时,各布告板的数据也要自动更新,并且后续可以自由添加或删除布告板。
类图
代码
//主题(被观察者)接口
public interface Subject {
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
//观察者接口
public interface Observer {
public void update(String s, int tmp);
}
//具体主题
public class WeatherData implements Subject {
private int temperature;
private String des;
//维护一个观察者列表
//不用关心具体的观察者对象是什么,只要实现了Observer接口就行
private ArrayList<Observer> observers;
public WeatherData() {
this.observers = new ArrayList();
}
@Override
public void addObserver(Observer observer) {
this.observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if (observers.indexOf(observer) >= 0) observers.remove(observer);
}
@Override
//状态发生变化时通知观察者更新
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(des,temperature);
}
}
public void setData(String des, int temperature) {
this.des = des;
this.temperature = temperature;
notifyObservers();
}
}
//具体观察者
//所有布告板也应该有一个Display父类,此处省略
public class CurrentDisplay implements Observer {
private String des;
private int temp;
//持有主题对象方便取消订阅时主题将自己删除
private Subject subject;
public CurrentDisplay(Subject subject) {
this.subject = subject;
subject.addObserver(this);
}
@Override
public void update(String des, int temp) {
this.des = des;
this.temp = temp;
display();
}
public void display() {
System.out.println(temp + " ℃ " + des);
}
}
观察者模式的推(push)和拉(pull)
推模式更“正确”
notifyObservers(Object data)
update(Subject subject,Object data)
notifyObservers(){
notifyObservers(null);
}
update(Subject subject,Object data){
if(subject instanceof WeatherData){
WeatherData weather = (WeatherData)subject;
this.temperature = weather.getTemperature();
}
}
Java内置的观察者模式
- Java API有内置的观察者模式。java.util包内有最基本的Observer接口和Observerable类。 然 而 它 们 从 J a v a 9 后 就 被 弃 用 了 ! \color{red}{然而它们从Java 9后就被弃用了!} 然而它们从Java9后就被弃用了!要想用观察者模式还得自己建。
- Java Swing中也有观察者模式的影子,比如各种listener。最常见的方法就是
addActionListener()
。