深入理解设计模式之观察者模式
深入理解设计模式之观察者模式(Observer Pattern)
一、什么是观察者模式?
观察者模式(Observer Pattern)是一种行为型设计模式。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象的状态发生变化时,所有依赖于它的观察者都会收到通知并自动更新。
通俗地说,观察者模式就是“发布-订阅”模式,主题(被观察者)负责发布消息,观察者负责订阅并响应消息。
二、观察者模式的结构
观察者模式主要包含以下角色:
- Subject(主题/被观察者):负责维护观察者列表,提供添加、删除观察者的方法,并在自身状态变化时通知所有观察者。
- Observer(观察者):定义响应通知的接口。
- ConcreteSubject(具体主题):实现主题的具体逻辑。
- ConcreteObserver(具体观察者):实现观察者的具体响应逻辑。
三、观察者模式的优缺点
优点
- 解耦:主题和观察者之间是抽象耦合,便于独立扩展和复用。
- 动态联动:支持动态添加、删除观察者,灵活性高。
- 广播机制:主题变化时可通知所有观察者,实现广播通信。
缺点
- 通知无顺序:通知观察者的顺序不可控,可能带来不确定性。
- 性能问题:观察者过多时,通知会耗时,影响性能。
- 循环依赖:可能导致循环调用,需注意防止。
四、典型应用场景
- 事件系统(如GUI事件监听、消息订阅等)
- 订阅-发布系统(如新闻订阅、微信公众号推送等)
- 数据模型与视图联动(如MVC模式中的Model-View)
五、Java实现示例
下面以“气象站”推送天气数据为例,演示观察者模式的实现。
1. 观察者接口
// 观察者接口
public interface Observer {void update(float temperature, float humidity, float pressure);
}
2. 主题接口
// 主题接口
public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}
3. 具体主题(气象站)
import java.util.ArrayList;
import java.util.List;// 具体主题
public class WeatherData implements Subject {private List<Observer> observers = new ArrayList<>();private float temperature;private float humidity;private float pressure;@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {observers.remove(o);}@Overridepublic void notifyObservers() {for (Observer o : observers) {o.update(temperature, humidity, pressure);}}// 当气象数据更新时调用public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;notifyObservers();}
}
4. 具体观察者
// 具体观察者
public class CurrentConditionsDisplay implements Observer {@Overridepublic void update(float temperature, float humidity, float pressure) {System.out.println("当前天气:温度=" + temperature + "℃, 湿度=" + humidity + "%, 气压=" + pressure + "hPa");}
}public class ForecastDisplay implements Observer {@Overridepublic void update(float temperature, float humidity, float pressure) {System.out.println("天气预报:温度=" + (temperature + 1) + "℃, 湿度=" + (humidity - 2) + "%, 气压=" + (pressure + 1) + "hPa");}
}
5. 客户端代码
public class Client {public static void main(String[] args) {WeatherData weatherData = new WeatherData();Observer currentDisplay = new CurrentConditionsDisplay();Observer forecastDisplay = new ForecastDisplay();weatherData.registerObserver(currentDisplay);weatherData.registerObserver(forecastDisplay);// 模拟气象数据变化weatherData.setMeasurements(25.0f, 65.0f, 1013.0f);System.out.println("----");weatherData.setMeasurements(28.0f, 70.0f, 1012.0f);}
}
6. 输出结果
当前天气:温度=25.0℃, 湿度=65.0%, 气压=1013.0hPa
天气预报:温度=26.0℃, 湿度=63.0%, 气压=1014.0hPa
----
当前天气:温度=28.0℃, 湿度=70.0%, 气压=1012.0hPa
天气预报:温度=29.0℃, 湿度=68.0%, 气压=1013.0hPa
六、总结
观察者模式是一种非常常用的设计模式,广泛应用于事件驱动、消息推送、数据联动等场景。它实现了对象之间的解耦,让系统更加灵活和可扩展。但在使用时也要注意性能和循环依赖等问题。
如需源码或有其他设计模式问题,欢迎留言交流!