目录
观察者模式属于行为型模式。在程序设计中,观察者模式通常由两个对象组成:观察者和被观察者。当被观察者状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应,所以也被称作“发布-订阅模式”。
主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。
观察者(Observer)的注册功能需要调用主题的 registerObserver() 方法。
案例:天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。
- public interface Subject {
- void resisterObserver(Observer o);
-
- void removeObserver(Observer o);
-
- void notifyObserver();
- }
- public class WeatherData implements Subject {
- private List
observers; - private float temperature;
- private float humidity;
- private float pressure;
-
- public WeatherData() {
- observers = new ArrayList<>();
- }
-
- public void setMeasurements(float temperature, float humidity, float pressure) {
- this.temperature = temperature;
- this.humidity = humidity;
- this.pressure = pressure;
- notifyObserver();
- }
-
- @Override
- public void resisterObserver(Observer o) {
- observers.add(o);
- }
-
- @Override
- public void removeObserver(Observer o) {
- int i = observers.indexOf(o);
- if (i >= 0) {
- observers.remove(i);
- }
- }
-
- @Override
- public void notifyObserver() {
- for (Observer o : observers) {
- o.update(temperature, humidity, pressure);
- }
- }
- }
- public interface Observer {
- void update(float temp, float humidity, float pressure);
- }
- public class StatisticsDisplay implements Observer {
- public StatisticsDisplay(Subject weatherData) {
- weatherData.resisterObserver(this);
- }
-
- @Override
- public void update(float temp, float humidity, float pressure) {
- System.out.println("StatisticsDisplay.update: " + temp + " " + humidity + " " + pressure);
- }
- }
- public class CurrentConditionsDisplay implements Observer {
- public CurrentConditionsDisplay(Subject weatherData) {
- weatherData.resisterObserver(this);
- }
-
- @Override
- public void update(float temp, float humidity, float pressure) {
- System.out.println("CurrentConditionsDisplay.update: " + temp + " " + humidity + " " + pressure);
- }
- }
- public class WeatherStation {
- public static void main(String[] args) {
- WeatherData weatherData = new WeatherData();
- CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
- StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
-
- weatherData.setMeasurements(0, 0, 0);
- weatherData.setMeasurements(1, 1, 1);
- }
- }
- CurrentConditionsDisplay.update: 0.0 0.0 0.0
- StatisticsDisplay.update: 0.0 0.0 0.0
- CurrentConditionsDisplay.update: 1.0 1.0 1.0
- StatisticsDisplay.update: 1.0 1.0 1.0
优点
1. 被观察者和观察者对象之间不需要知道对方的具体实现,只需要知道对方的接口,避免了紧耦合的关系。
2. 由于被观察者对象并不关心具体的观察者是谁,所以在程序运行的过程中,可以动态地增加或者删除观察者对象,增加了灵活性。
3. 符合开闭原则,当需要添加新的观察者时,只需要添加一个实现观察者接口的类,而不需要修改被观察者对象的代码。
缺点
1. 当观察者没有被正确移除时,可能会导致内存泄漏的问题。
2. 实现观察者模式,需要定义多个接口和类,增加了程序的复杂度。
3. 在某些情况下,被观察者和观察者对象之间可能出现循环依赖的问题。
JDK中的命令模式
java.util.Observer
java.util.EventListener
javax.servlet.http.HttpSessionBindingListener