基本概念
观察者模式 Observer 属于行为模式,在一对多关系中,主要解决的问题是当一个对象发生变化之后,自动通知其他依赖的对象做相应的操作。核心在Subject中有一个集合管理所有的Observer当发生特定变化的之后notify所有的Observer做相应的update操作。
UML
角色分析
Observer 观察者或订阅者 核心方法update 由Subject 主体调用 在一对多关系中 多的一方
Subject 主题 类似一个公告板 在一对多关系 对应一的部门
ConcreteSubject 具体的Subject实现类
ConcreteObserver 具体Observer 实现类
Client 客户端
代码实现
现在有一个气象站,气象站会更新当前的最新的气温和气压数据,传统的方式是所有关注到气象站的对象自己去重新获取一下最新的天气数据。现在采用观察者模式,比如百度天气,和新浪天气都订阅了气象站的天气服务,当气象站发生变化的时候就自动通知所有他下面的订阅者该更新天气了,而无需订阅者自己去重新调用获取最新数据。
// Observer观察者
public interface Observer {
// 当发生变化的时候的操作
void update(float temperature, float pressure);
}
// 具体的订阅者
public class SinaWeatherObserver implements Observer {
private float temperature;
private float pressure;
@Override
public void update(float temperature, float pressure) {
this.temperature = temperature;
this.pressure = pressure;
System.out.println(String.format("新浪天气更新气温%.2f,气压%.2f", temperature, pressure));
}
}
// 具体的订阅者
public class SinaWeatherObserver implements Observer {
private float temperature;
private float pressure;
@Override
public void update(float temperature, float pressure) {
this.temperature = temperature;
this.pressure = pressure;
System.out.println(String.format("新浪天气更新气温%.2f,气压%.2f", temperature, pressure));
}
}
// 主体
public interface Subject {
// 注册订阅者
void registerObserver(Observer observer);
// 通知订阅者
void notifyObserver();
// 删除订阅者
void removeObserver(Observer observer);
}
public class WeatherSubject implements Subject {
private float temperature = 26.5f;
private float pressure = 30f;
// 订阅者集合
List<Observer> observerList;
public WeatherSubject() {
this.observerList = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
public void changeData(float temperature, float pressure) {
this.temperature = temperature;
this.pressure = pressure;
// 天气发生的变化 调用通知方法
this.notifyObserver();
}
@Override
public void notifyObserver() {
for (Observer observer : observerList) {
// 遍历所有观察者 通知更新
observer.update(this.temperature, this.pressure);
}
}
@Override
public void removeObserver(Observer observer) {
if (observerList.contains(observer)) {
observerList.remove(observer);
return;
}
throw new NoSuchElementException();
}
}
使用细节
-
使用观察者模式让观察者和主体解耦 非常适合来处理1:N 在1改变之后对应N也做相应处理的场景
类似公告板,当公告板内容发生变化之后,通知所有关注了公告板的用户最新的数据,用户根据最新的数据做出自己需要的逻辑处理
-
以集合的方式来管理观察者方便添加 删除 通知
-
缺点在于如果观察者过多,通知到所有的观察者会话费很多时间,如果观察者和主体发生循环依赖则可能会造成系统的崩溃