观察者模式
- 观察者定义
观察者模式又被称为发布订阅模式。它定义了对象之间一对多的依赖,当一个对象状态发生改变时,它的所有依赖者都会收到通知并自动更新相关内容
观察者的定义很容易理解不做过多解释,即发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。
- 观察者类图
Subject:被观察者接口,里面定义了几个方法需要具体的观察者去实现。
WeatherData:具体的观察者,它将所有观察者对象的引用保存在一个集合中。
Observer:是抽象的“观察”角色,它定义了一个更新接口,使得在被观察者状态发生改变时通知自己。
CurrentCondition:具体的观察者
- 代码示例
下面我们以气象站发布天气,各大网站订阅气象站发布的天气消息为例。
Subject
public interface Subject {
void registerObserver(Observer observer);
void remove(Observer observer);
void notifyObserver();
}
WeatherData
public class WeatherData implements Subject {
// 观察者集合
private List<Observer> observerList = new ArrayList<>();
// 天气情况
private String weather;
public WeatherData() {
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
// 天气变化,通知观察者
notifyObserver();
}
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void remove(Observer observer) {
if (observerList.contains(observer)) {
observerList.remove(observer);
}
}
@Override
public void notifyObserver() {
if (observerList != null && !observerList.isEmpty()) {
for (Observer observer : observerList) {
observer.updateWeather(weather);
}
}
}
}
Observer
public interface Observer {
void updateWeather(String weather);
}
具体的观察者类:
public class Sina implements Observer {
@Override
public void updateWeather(String weather) {
System.out.println("新浪天气变化为:"+ weather);
}
}
//
public class Baidu implements Observer {
@Override
public void updateWeather(String weather) {
System.out.println("百度天气变化为:" + weather);
}
}
测试:
public class MyClient {
public static void main(String[] args) {
// 建立气象站
WeatherData weatherData = new WeatherData();
// 往气象站注册观察者
weatherData.registerObserver(new Baidu());
weatherData.registerObserver(new Sina());
// 给气象站设置天气信息,会通知订阅的观察者
weatherData.setWeather("晴天");
// 天气又变化为阴天
weatherData.setWeather("阴天");
}
}
测试结果
百度天气变化为:晴天
新浪天气变化为:晴天
百度天气变化为:阴天
新浪天气变化为:阴天
分析:
- 上的代码很简单,主要的核心是WeatherData 类里面管理了一个观察者集合。
- 当有新的观察者需要加入的时候,只需要实现Observer接口,然后再客户端里面把观察者注册进去就可以。
观察者源码在JDK中分析
Java中的观察者模式主题需要继承java.util.Observable,观察者需要实现java.util.Observer。通过notifyObservers()方法发送通知,在调用此方法之前需要调用setChanged()修改发送状态。大家可以去查看源码,原理和上面例子类似。