观察者模式指南:事件驱动的优雅实现
本文将详细介绍观察者模式的原理和最佳实践,帮助开发者构建高效的事件驱动系统。
·
观察者模式指南:事件驱动的优雅实现
📖 你有没有遇到过这些问题?
想象一下这些生活场景:
场景1:新闻订阅
方式A:每天主动打电话问每个朋友"有什么新闻吗?"
方式B:订阅新闻推送,有新闻时自动收到通知哪种方式更高效?
场景2:股票监控
方式A:不停地刷新股票软件查看价格变化
方式B:设置价格提醒,达到目标价格时自动通知哪种方式更智能?
在编程中,观察者模式就像新闻订阅和股票提醒一样重要!
轮询检查像不停打电话询问一样低效:
// ❌ 轮询方式,效率低下
void main_loop(void)
{
while (1)
{
// 不停地检查各种状态
if (sensor_data_changed())
{
update_display();
send_to_comm();
check_alarm_conditions();
}
if (button_pressed())
{
update_menu();
refresh_display();
}
if (timer_expired())
{
save_data();
reset_timer();
}
// 浪费CPU资源不停轮询
delay_ms(10);
}
}
观察者模式像智能通知一样高效:
// ✅ 观察者模式,事件驱动
void sensor_data_ready_handler(const SensorData_t *data)
{
// 传感器数据就绪时自动调用
DisplayModule_UpdateData(data);
CommModule_SendData(data);
AlarmModule_CheckThresholds(data);
}
void button_press_handler(ButtonEvent_t event)
{
// 按键按下时自动调用
MenuModule_ProcessInput(event);
DisplayModule_Refresh();
}
void setup_observers(void)
{
// 注册观察者
SensorModule_AddObserver(sensor_data_ready_handler);
ButtonModule_AddObserver(button_press_handler);
}
本文将详细介绍观察者模式的原理和最佳实践,帮助开发者构建高效的事件驱动系统。
🎯 为什么需要观察者模式?
生活中的例子
场景1:微信群通知
传统方式:每个人定时问群主"有新消息吗?"
观察者模式:有新消息时群主自动@所有人
场景2:火警系统
传统方式:保安每隔几分钟巡查一遍所有房间
观察者模式:烟雾探测器检测到火情时自动报警
观察者模式的价值
- 降低耦合度:发布者不需要知道具体的订阅者
- 提高响应性:事件发生时立即通知,无延迟
- 节省资源:避免无效的轮询检查
- 易于扩展:新增观察者不影响现有代码
🌟 观察者模式基本结构
1. 核心组件
主题(Subject)和观察者(Observer)
// 观察者接口定义
typedef void (*EventHandler_t)(const void *event_data, void *user_data);
// 观察者结构
typedef struct Observer
{
EventHandler_t handler; // 事件处理函数
void *user_data; // 用户数据
struct Observer *next; // 链表指针
} Observer_t;
// 主题结构
typedef struct Subject
{
Observer_t *observers; // 观察者链表
const char *name; // 主题名称
uint32_t observer_count; // 观察者数量
} Subject_t;
// 主题操作接口
bool Subject_Init(Subject_t *subject, const char *name);
bool Subject_AddObserver(Subject_t *subject, EventHandler_t handler, void *user_data);
bool Subject_RemoveObserver(Subject_t *subject, EventHandler_t handler);
void Subject_NotifyObservers(Subject_t *subject, const void *event_data);
void Subject_Cleanup(Subject_t *subject);
2. 基础实现
观察者管理核心代码
// subject.c - 观察者模式核心实现
#include "observer_pattern.h"
#include <stdlib.h>
#include <string.h>
/**
* @brief 初始化主题
* @param subject 主题对象
* @param name 主题名称
* @return 初始化结果
*/
bool Subject_Init(Subject_t *subject, const char *name)
{
if (subject == NULL)
{
return false;
}
subject->observers = NULL;
subject->name = name;
subject->observer_count = 0;
return true;
}
/**
* @brief 添加观察者
* @param subject 主题对象
* @param handler 事件处理函数
* @param user_data 用户数据
* @return 添加结果
*/
bool Subject_AddObserver(Subject_t *subject, EventHandler_t handler, void *user_data)
{
if (subject == NULL || handler == NULL)
{
return false;
}
// 检查是否已存在
Observer_t *current = subject->observers;
while (current != NULL)
{
if (current->handler == handler && current->user_data == user_data)
{
return false; // 已存在
}
current = current->next;
}
// 创建新观察者
Observer_t *new_observer = (Observer_t*)malloc(sizeof(Observer_t));
if (new_observer == NULL)
{
return false;
}
new_observer->handler = handler;
new_observer->user_data = user_data;
new_observer->next = subject->observers;
subject->observers = new_observer;
subject->observer_count++;
return true;
}
/**
* @brief 移除观察者
* @param subject 主题对象
* @param handler 事件处理函数
* @return 移除结果
*/
bool Subject_RemoveObserver(Subject_t *subject, EventHandler_t handler)
{
if (subject == NULL || handler == NULL)
{
return false;
}
Observer_t **current = &subject->observers;
while (*current != NULL)
{
if ((*current)->handler == handler)
{
Observer_t *to_remove = *current;
*current = (*current)->next;
free(to_remove);
subject->observer_count--;
return true;
}
current = &(*current)->next;
}
return false; // 未找到
}
/**
* @brief 通知所有观察者
* @param subject 主题对象
* @param event_data 事件数据
*/
void Subject_NotifyObservers(Subject_t *subject, const void *event_data)
{
if (subject == NULL)
{
return;
}
Observer_t *current = subject->observers;
while (current != NULL)
{
if (current->handler != NULL)
{
current->handler(event_data, current->user_data);
}
current = current->next;
}
}
/**
* @brief 清理主题资源
* @param subject 主题对象
*/
void Subject_Cleanup(Subject_t *subject)
{
if (subject == NULL)
{
return;
}
Observer_t *current = subject->observers;
while (current != NULL)
{
Observer_t *next = current->next;
free(current);
current = next;
}
subject->observers = NULL;
subject->observer_count = 0;
}
3. 类型安全的观察者
强类型事件系统
// typed_observer.h - 类型安全的观察者模式
// 传感器数据事件
typedef struct
{
float temperature;
float pressure;
float humidity;
uint32_t timestamp;
} SensorDataEvent_t;
// 按键事件
typedef struct
{
uint8_t key_id;
bool is_pressed;
uint32_t press_duration;
} ButtonEvent_t;
// 报警事件
typedef struct
{
uint8_t alarm_type;
uint8_t severity;
char message[64];
} AlarmEvent_t;
// 类型安全的事件处理器
typedef void (*SensorDataHandler_t)(const SensorDataEvent_t *event, void *user_data);
typedef void (*ButtonEventHandler_t)(const ButtonEvent_t *event, void *user_data);
typedef void (*AlarmEventHandler_t)(const AlarmEvent_t *event, void *user_data);
// 类型安全的主题
typedef struct
{
Subject_t base;
} SensorDataSubject_t;
typedef struct
{
Subject_t base;
} ButtonEventSubject_t;
typedef struct
{
Subject_t base;
} AlarmEventSubject_t;
// 类型安全的接口
bool SensorDataSubject_AddObserver(SensorDataSubject_t *subject, SensorDataHandler_t handler, void *user_data);
void SensorDataSubject_NotifyObservers(SensorDataSubject_t *subject, const SensorDataEvent_t *event);
bool ButtonEventSubject_AddObserver(ButtonEventSubject_t *subject, ButtonEventHandler_t handler, void *user_data);
void ButtonEventSubject_NotifyObservers(ButtonEventSubject_t *subject, const ButtonEvent_t *event);
bool AlarmEventSubject_AddObserver(AlarmEventSubject_t *subject, AlarmEventHandler_t handler, void *user_data);
void AlarmEventSubject_NotifyObservers(AlarmEventSubject_t *subject, const AlarmEvent_t *event);
🎨 实际应用场景
1. LFS流量计传感器数据通知
传感器数据发布订阅
// sensor_publisher.c - 传感器数据发布者
static SensorDataSubject_t sensor_data_subject;
// 初始化传感器发布者
void SensorPublisher_Init(void)
{
Subject_Init(&sensor_data_subject.base, "SensorData");
}
// 传感器数据读取和发布
void SensorPublisher_Update(void)
{
static uint32_t last_read_time = 0;
uint32_t current_time = GetSystemTick();
// 每100ms读取一次传感器数据
if (current_time - last_read_time >= 100)
{
SensorDataEvent_t event;
// 读取传感器数据
event.temperature = ReadTemperatureSensor();
event.pressure = ReadPressureSensor();
event.humidity = ReadHumiditySensor();
event.timestamp = current_time;
// 通知所有观察者
SensorDataSubject_NotifyObservers(&sensor_data_subject, &event);
last_read_time = current_time;
}
}
// 添加传感器数据观察者
bool SensorPublisher_AddObserver(SensorDataHandler_t handler, void *user_data)
{
return SensorDataSubject_AddObserver(&sensor_data_subject, handler, user_data);
}
多个模块订阅传感器数据
// display_module.c - 显示模块(观察者)
void display_sensor_data_handler(const SensorDataEvent_t *event, void *user_data)
{
// 更新显示内容
LCD_ShowFloat(0, 0, "Temp: %.1f°C", event->temperature);
LCD_ShowFloat(0, 20, "Press: %.1fkPa", event->pressure);
LCD_ShowFloat(0, 40, "Humid: %.1f%%", event->humidity);
printf("显示模块:更新传感器数据显示\n");
}
void DisplayModule_Init(void)
{
// 订阅传感器数据
SensorPublisher_AddObserver(display_sensor_data_handler, NULL);
}
// communication_module.c - 通信模块(观察者)
void comm_sensor_data_handler(const SensorDataEvent_t *event, void *user_data)
{
// 检查是否有数据请求
if (CommModule_HasDataRequest())
{
// 发送传感器数据
char data_string[128];
snprintf(data_string, sizeof(data_string),
"TEMP:%.1f,PRESS:%.1f,HUMID:%.1f,TIME:%lu",
event->temperature, event->pressure,
event->humidity, event->timestamp);
CommModule_SendString(data_string);
printf("通信模块:发送传感器数据\n");
}
}
void CommModule_Init(void)
{
// 订阅传感器数据
SensorPublisher_AddObserver(comm_sensor_data_handler, NULL);
}
// alarm_module.c - 报警模块(观察者)
void alarm_sensor_data_handler(const SensorDataEvent_t *event, void *user_data)
{
// 检查报警条件
if (event->temperature > TEMP_ALARM_THRESHOLD)
{
AlarmEvent_t alarm_event = {
.alarm_type = ALARM_TYPE_HIGH_TEMPERATURE,
.severity = ALARM_SEVERITY_HIGH,
};
snprintf(alarm_event.message, sizeof(alarm_event.message),
"温度过高: %.1f°C", event->temperature);
// 触发报警事件
AlarmEventSubject_NotifyObservers(&alarm_subject, &alarm_event);
printf("报警模块:温度报警触发\n");
}
}
void AlarmModule_Init(void)
{
// 订阅传感器数据
SensorPublisher_AddObserver(alarm_sensor_data_handler, NULL);
}
2. 按键事件处理系统
按键事件发布者
// button_publisher.c - 按键事件发布者
static ButtonEventSubject_t button_event_subject;
void ButtonPublisher_Init(void)
{
Subject_Init(&button_event_subject.base, "ButtonEvent");
}
// 按键扫描和事件发布
void ButtonPublisher_Scan(void)
{
static uint8_t last_key_state[MAX_KEYS] = {0};
static uint32_t key_press_time[MAX_KEYS] = {0};
for (uint8_t i = 0; i < MAX_KEYS; i++)
{
uint8_t current_state = ReadKeyState(i);
uint32_t current_time = GetSystemTick();
// 检测按键状态变化
if (current_state != last_key_state[i])
{
ButtonEvent_t event = {
.key_id = i,
.is_pressed = current_state,
.press_duration = current_state ? 0 : (current_time - key_press_time[i])
};
if (current_state)
{
key_press_time[i] = current_time;
}
// 发布按键事件
ButtonEventSubject_NotifyObservers(&button_event_subject, &event);
last_key_state[i] = current_state;
}
}
}
bool ButtonPublisher_AddObserver(ButtonEventHandler_t handler, void *user_data)
{
return ButtonEventSubject_AddObserver(&button_event_subject, handler, user_data);
}
菜单系统订阅按键事件
// menu_module.c - 菜单模块(按键事件观察者)
void menu_button_handler(const ButtonEvent_t *event, void *user_data)
{
if (!event->is_pressed) // 按键释放时处理
{
switch (event->key_id)
{
case KEY_UP:
MenuModule_MoveCursorUp();
break;
case KEY_DOWN:
MenuModule_MoveCursorDown();
break;
case KEY_ENTER:
if (event->press_duration > LONG_PRESS_TIME)
{
MenuModule_EnterSubMenu();
}
else
{
MenuModule_SelectItem();
}
break;
case KEY_BACK:
MenuModule_GoBack();
break;
}
// 更新菜单显示
MenuModule_UpdateDisplay();
printf("菜单模块:处理按键 %d\n", event->key_id);
}
}
void MenuModule_Init(void)
{
// 订阅按键事件
ButtonPublisher_AddObserver(menu_button_handler, NULL);
}
🔧 高级观察者模式技巧
1. 优先级观察者
按优先级通知观察者
// priority_observer.h - 优先级观察者
typedef enum
{
OBSERVER_PRIORITY_LOW = 0,
OBSERVER_PRIORITY_NORMAL,
OBSERVER_PRIORITY_HIGH,
OBSERVER_PRIORITY_CRITICAL
} ObserverPriority_t;
typedef struct PriorityObserver
{
EventHandler_t handler;
void *user_data;
ObserverPriority_t priority;
struct PriorityObserver *next;
} PriorityObserver_t;
typedef struct
{
PriorityObserver_t *observers[4]; // 按优先级分组
uint32_t observer_counts[4];
} PrioritySubject_t;
// 按优先级添加观察者
bool PrioritySubject_AddObserver(PrioritySubject_t *subject,
EventHandler_t handler,
void *user_data,
ObserverPriority_t priority);
// 按优先级顺序通知观察者
void PrioritySubject_NotifyObservers(PrioritySubject_t *subject, const void *event_data)
{
// 从高优先级到低优先级通知
for (int priority = OBSERVER_PRIORITY_CRITICAL; priority >= OBSERVER_PRIORITY_LOW; priority--)
{
PriorityObserver_t *current = subject->observers[priority];
while (current != NULL)
{
if (current->handler != NULL)
{
current->handler(event_data, current->user_data);
}
current = current->next;
}
}
}
2. 异步观察者
非阻塞事件通知
// async_observer.h - 异步观察者
#include "task_queue.h"
typedef struct
{
EventHandler_t handler;
void *event_data;
size_t data_size;
void *user_data;
} AsyncEventTask_t;
typedef struct
{
Subject_t sync_subject; // 同步观察者
TaskQueue_t *async_queue; // 异步任务队列
} AsyncSubject_t;
// 异步主题初始化
bool AsyncSubject_Init(AsyncSubject_t *subject, const char *name, size_t queue_size)
{
if (!Subject_Init(&subject->sync_subject, name))
{
return false;
}
subject->async_queue = TaskQueue_Create(queue_size);
return subject->async_queue != NULL;
}
// 添加同步观察者
bool AsyncSubject_AddSyncObserver(AsyncSubject_t *subject, EventHandler_t handler, void *user_data)
{
return Subject_AddObserver(&subject->sync_subject, handler, user_data);
}
// 添加异步观察者
bool AsyncSubject_AddAsyncObserver(AsyncSubject_t *subject, EventHandler_t handler, void *user_data)
{
// 异步观察者通过任务队列处理
return true; // 实现省略
}
// 通知观察者(同步+异步)
void AsyncSubject_NotifyObservers(AsyncSubject_t *subject, const void *event_data, size_t data_size)
{
// 立即通知同步观察者
Subject_NotifyObservers(&subject->sync_subject, event_data);
// 将异步观察者任务加入队列
// 实现省略...
}
// 处理异步事件(在后台任务中调用)
void AsyncSubject_ProcessAsyncEvents(AsyncSubject_t *subject)
{
AsyncEventTask_t task;
while (TaskQueue_Dequeue(subject->async_queue, &task))
{
if (task.handler != NULL)
{
task.handler(task.event_data, task.user_data);
}
// 释放事件数据内存
if (task.event_data != NULL)
{
free(task.event_data);
}
}
}
📚 参考资料
设计模式
- Observer Pattern - 观察者模式详解
- Gang of Four Design Patterns - 经典设计模式
- Publisher-Subscriber Pattern - 发布订阅模式
- Event-Driven Architecture - 事件驱动架构
嵌入式应用
- Embedded Observer Pattern - 嵌入式观察者模式
- Event-Driven Embedded Systems - 事件驱动嵌入式系统
- Interrupt-Driven Programming - 中断驱动编程
- Real-Time Event Processing - 实时事件处理
🏷️ 总结
观察者模式就像智能通知系统:
- 发布订阅让模块间松散耦合
- 事件驱动提高系统响应性
- 自动通知避免无效轮询
- 易于扩展支持动态添加观察者
核心原则:
- 松散耦合 > 紧密依赖
- 事件驱动 > 轮询检查
- 自动通知 > 主动查询
- 类型安全 > 通用接口
记住这个公式:
优秀的观察者模式 = 松散耦合 + 事件驱动 + 自动通知 + 类型安全
通过本文的学习,我们了解了观察者模式的原理和最佳实践,掌握了构建高效事件驱动系统的方法。
观察者模式是事件驱动编程的核心,让你的代码像智能通知系统一样高效响应! 👁️
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)