前言
观察者,即时observer,总结来说就是一个当一个被观察的对象的状态发生变化时,会通知相应的观察者对象。
观察者模式定义了四种角色:抽象主题、具体主题、抽象观察者、具体观察者
- 抽象主题(Subject):通常为接口或抽象类,定义一系列操作,如订阅,取消订阅,通知等方法
- 具体主题(Concrete Subject):具体主题,继承或实现抽象主题,实现相应的逻辑,如维护与观察者的关系,将自身的状态变化告知观察者。
- 抽象观察者(Observer):定义观察者行为
- 具体观察者(Concrete Observer):实现观察者行为,实现收到被观察者的通知后将要处理的逻辑
实例
场景
微信公众号消息的订阅与推送,我订阅了公众号,我就是观察者,公众号是被观察者,当公众号发表了新文章时,即被观察者的状态发生改变,公众号会给我推送通知
/**
* 抽象观察者
*/
public interface IObserver {
void update(String message);
}
/**
* 抽象主题
*/
public interface ISubject {
//订阅
public void registerObserver(IObserver observer);
//取消订阅
public void unregisterObserver(IObserver observer);
//通知
public void notifyObserver(String message);
}
/**
* 具体观察者
*/
public class Observer implements IObserver {
@Override
public void update(String message) {
System.out.println("我收到了通知:"+message);
}
}
/**
* 具体主题:实现一系列逻辑操作,维护与观察者的关系
*/
public class Subject implements ISubject {
private List<IObserver> list = new ArrayList<>();
@Override
public void registerObserver(IObserver observer) {
list.add(observer);
}
@Override
public void unregisterObserver(IObserver observer) {
list.remove(observer);
}
@Override
public void notifyObserver(String message) {
list.forEach(o -> o.update(message));
}
}
测试:
输出结果:
总结
观察者模式在有的书里又称为发布/订阅模式,当需要对某个对象的状态进行检测时,则可以使用该设计模式。例如观察检测温度超过某阈值时,向APP推送短信提醒。
与MQTT协议的话题订阅推送其实是类似的,基本流程都是先订阅维护一个关系,在有状态变化时则给相应的观察者推送数据,唯一不同的是观察与被观察的关系是由谁来维护。
Java中的观察者模式
Java内置了观察者模式
Java提供了一个Observable类,顾名思义可知“可观察的”。当你有一个类需要被观察时,需要继承此类。
Java还提供了一个Observer接口,顾名思义可知“观察者”。当你有一个类需要观察别的类时,需要实现此接口。
public class Fire extends Observable {
private String temperature;
public void temperatureChange() {
setChanged();
notifyObservers();
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
temperatureChange();
}
}
public class Watcher implements Observer{
private Observable observable;
private String temperature;
public Watcher(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof Fire) {
Fire fire = (Fire) o;
this.temperature = fire.getTemperature();
display();
}
}
public void display() {
System.out.println(this.toString());
}
@Override
public String toString() {
return "Fire:" + temperature;
}
}
测试:
输出结果: