当一个对象更改状态,可以自动通知并更新其所有依赖项(观察者),就像是事件总线,谁有监听,有消息时谁就会收到此消息
使用场景
当一个对象的状态改变,希望其它不知道是谁的对象也能够及时更新并且保证低耦合
代码示例
import java.util.ArrayList;
import java.util.List;
/**
* 可以通过此接口注册来监听天气情况
*/
public class Weather {
private String currentWeather;
/**
* 所有的观察者集合
*/
private List<WeatherObserver> observers;
public Weather() {
observers = new ArrayList<>();
}
/**
* 添加观察者
*
* @param obs 观察者
*/
public void addObserver(WeatherObserver obs) {
observers.add(obs);
}
/**
* 移除观察者
*
* @param obs 需要移除的观察者
*/
public void removeObserver(WeatherObserver obs) {
observers.remove(obs);
}
/**
* 设置天气
*
* @param weather
*/
public void setCurrentWeather(String weather) {
currentWeather = weather;
// 通知观察者
notifyObservers();
}
/**
* 通知所有观察者
*
*/
private void notifyObservers() {
for (WeatherObserver obs : observers) {
obs.update(currentWeather);
}
}
}
/**
* 观察者接口
*/
public interface WeatherObserver {
/**
* 更新方法
*
* @param currentWeather 天气
*/
void update(String currentWeather);
}
/**
* 渔民观察者
*/
public class FishermanObserver implements WeatherObserver {
@Override
public void update(String currentWeather) {
System.out.println("渔民收到的天气 = " + currentWeather);
}
}
/**
* 农场主观察者
*/
public class FarmerObserver implements WeatherObserver {
@Override
public void update(String currentWeather) {
System.out.println("农场主收到的天气 = " + currentWeather);
}
}
/**
* 演示当天气改变了如何通知所有观察者(农民或渔民)
*
* @author July
* @date 2020/10/20
*/
public class App {
public static void main(String[] args) {
// 普通的观察者
Weather weather = new Weather();
weather.addObserver(new FishermanObserver());
weather.addObserver(new FarmerObserver());
// 改变天气,所有注册到目标观察者管理对象的观察者都会收到消息
weather.setCurrentWeather("rainy day");
}
}
角色说明
- Subject(Weather):也叫被观察者,主要的对象,负责管理观察者和改变后通知观察者
- Observer (WeatherObserver):观察者接口,所有观察者都需要实现
- Concrete Observer(FishermanObserver、FarmerObserver):具体观察者的实现
优缺点
优点
- 观察者和被观察者是抽象耦合的
- 建立一套触发机制
缺点
- 如果观察者太多,通知所有观察者需要花费比较多的时间
- 观察者和被观察者有相互调用,可能会触发循环调用
扩展
对于有多个观察目标的情况,需要抽象出
AbstractWeather
,所有观察目标都实现
AbstractWeather
抽象类,一个观察者可以观察多个目标,一个目标可以被多个观察者观察
版权声明:本文为qq_32828253原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。