设计模式-观察者模式
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。观察者模式常用于事件驱动的系统中,比如发布订阅系统、GUI 事件模型等。
观察者模式的关键角色:
- 主题(Subject):
- 被观察的对象,维护一个观察者列表,提供添加、移除观察者的方法,并在自身状态发生变化时通知观察者。
- 观察者(Observer):
- 接收通知并更新状态的对象。通常需要实现一个更新方法。
- 具体主题(ConcreteSubject):
- 实现主题接口,保存具体状态,并在状态改变时通知观察者。
- 具体观察者(ConcreteObserver):
- 实现观察者接口,定义具体的更新逻辑。
示例代码:天气预报系统
问题背景
假设有一个天气预报系统,当天气发生变化时,需要通知多个设备(手机、平板、显示屏等)。
实现代码
// 1. 抽象观察者接口
interface Observer {
void update(String weather);
}
// 2. 抽象主题接口
interface Subject {
void addObserver(Observer observer); // 添加观察者
void removeObserver(Observer observer); // 移除观察者
void notifyObservers(); // 通知所有观察者
}
// 3. 具体主题(WeatherStation)
class WeatherStation implements Subject {
private List<Observer> observers = new ArrayList<>(); // 保存观察者
private String weather; // 天气状态
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(weather); // 通知每个观察者
}
}
// 设置天气并通知观察者
public void setWeather(String weather) {
this.weather = weather;
System.out.println("天气更新为: " + weather);
notifyObservers();
}
}
// 4. 具体观察者(手机)
class MobileDevice implements Observer {
private String name;
public MobileDevice(String name) {
this.name = name;
}
@Override
public void update(String weather) {
System.out.println(name + " 收到天气更新: " + weather);
}
}
// 5. 具体观察者(显示屏)
class DisplayScreen implements Observer {
@Override
public void update(String weather) {
System.out.println("显示屏更新天气: " + weather);
}
}
// 6. 客户端
public class ObserverPatternExample {
public static void main(String[] args) {
// 创建主题
WeatherStation weatherStation = new WeatherStation();
// 创建观察者
Observer mobile1 = new MobileDevice("手机A");
Observer mobile2 = new MobileDevice("手机B");
Observer display = new DisplayScreen();
// 注册观察者
weatherStation.addObserver(mobile1);
weatherStation.addObserver(mobile2);
weatherStation.addObserver(display);
// 更新天气,通知观察者
weatherStation.setWeather("晴天");
weatherStation.setWeather("下雨");
// 移除一个观察者
weatherStation.removeObserver(mobile2);
// 再次更新天气
weatherStation.setWeather("多云");
}
}
输出结果:
天气更新为: 晴天
手机A 收到天气更新: 晴天
手机B 收到天气更新: 晴天
显示屏更新天气: 晴天
天气更新为: 下雨
手机A 收到天气更新: 下雨
手机B 收到天气更新: 下雨
显示屏更新天气: 下雨
天气更新为: 多云
手机A 收到天气更新: 多云
显示屏更新天气: 多云
观察者模式的优点:
- 松耦合:主题和观察者之间的耦合性较低,便于扩展和维护。
- 动态联动:可以动态地添加或移除观察者,无需修改主题代码。
- 灵活性:多个观察者可以独立接收通知,并做出不同的处理。
观察者模式的缺点:
- 性能问题:如果观察者过多或通知频繁,可能会影响性能。
- 调试困难:通知链较长时,可能难以跟踪状态变化。
观察者模式的适用场景:
- 一个对象的改变需要通知其他对象时。
- 系统需要动态添加或移除观察者时。
- 常见应用场景包括事件监听器、消息队列、发布-订阅系统等。
观察者模式在实际开发中非常常见,比如 GUI 系统中的事件处理(监听器模式)、数据模型与视图的同步(如 MVC 模式)等。