嵌入式设计模式之观察者模式(1)
·
观察者模式的核心思想
观察者模式(Observer Pattern),这是在嵌入式系统中极其重要且广泛应用的一种行为型设计模式。
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
简单比喻
- 主题(Subject):就像微信公众号平台
- 观察者(Observer):就像订阅公众号的用户
- 通知机制:公众号发布新文章时,所有订阅者自动收到推送
观察者模式解决的嵌入式问题
典型问题场景
- 传感器数据分发:一个温度传感器数据变化,需要同时通知显示屏、报警器、数据记录器
- 事件处理:按键按下事件需要同时触发界面更新、业务逻辑、声音反馈
- 状态监控:电池电量变化需要通知功耗管理、UI显示、预警系统
- 通信消息:收到网络数据包需要分发给多个处理模块
传统做法的困境
// 紧耦合的实现方式(不推荐)
void temperature_update(float temp) {
// 需要手动调用各个模块
display_update_temperature(temp);
alarm_check_temperature(temp);
logger_record_temperature(temp);
network_send_temperature(temp);
// 添加新模块需要修改这里!
}
// 问题:主题模块需要知道所有观察者的具体实现,违反开闭原则
观察者模式的结构与实现
基本结构组成


嵌入式观察者模式具体实现
1. 定义观察者接口
// observer.h
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include <stdint.h>
// 前向声明
typedef struct Subject Subject;
// 观察者接口
typedef struct {
void (*update)(void* observer, Subject* subject, void* data);
void (*destroy)(void* observer);
} ObserverInterface;
// 主题基类
typedef struct Subject {
ObserverInterface** observers;
uint16_t max_observers;
uint16_t observer_count;
void* context; // 主题特定数据
} Subject;
// 主题操作函数
int subject_attach(Subject* subject, ObserverInterface* observer);
int subject_detach(Subject* subject, ObserverInterface* observer);
void subject_notify(Subject* subject, void* data);
#endif
2. 主题实现
// subject.c
#include "observer.h"
#include <string.h>
#define MAX_OBSERVERS 10
// 创建主题
Subject* subject_create(uint16_t max_obs) {
Subject* subject = malloc(sizeof(Subject));
if (!subject) return NULL;
subject->max_observers = (max_obs > 0) ? max_obs : MAX_OBSERVERS;
subject->observer_count = 0;
subject->context = NULL;
subject->observers = malloc(sizeof(ObserverInterface*) * subject->max_observers);
if (!subject->observers) {
free(subject);
return NULL;
}
memset(subject->observers, 0, sizeof(ObserverInterface*) * subject->max_observers);
return subject;
}
// 附加观察者
int subject_attach(Subject* subject, ObserverInterface* observer) {
if (!subject || !observer || subject->observer_count >= subject->max_observers) {
return -1;
}
// 检查是否已附加
for (int i = 0; i < subject->observer_count; i++) {
if (subject->observers[i] == observer) {
return -2; // 已存在
}
}
subject->observers[subject->observer_count++] = observer;
return 0;
}
// 分离观察者
int subject_detach(Subject* subject, ObserverInterface* observer) {
if (!subject || !observer) return -1;
for (int i = 0; i < subject->observer_count; i++) {
if (subject->observers[i] == observer) {
// 移动后续元素
for (int j = i; j < subject->observer_count - 1; j++) {
subject->observers[j] = subject->observers[j + 1];
}
subject->observer_count--;
subject->observers[subject->observer_count] = NULL;
return 0;
}
}
return -2; // 未找到
}
// 通知所有观察者
void subject_notify(Subject* subject, void* data) {
if (!subject) return;
for (int i = 0; i < subject->observer_count; i++) {
if (subject->observers[i] && subject->observers[i]->update) {
subject->observers[i]->update(subject->observers[i], subject, data);
}
}
}
// 销毁主题
void subject_destroy(Subject* subject) {
if (subject) {
if (subject->observers) {
free(subject->observers);
}
free(subject);
}
}
3. 具体主题:温度传感器
// temperature_sensor.h
#ifndef _TEMPERATURE_SENSOR_H_
#define _TEMPERATURE_SENSOR_H_
#include "observer.h"
typedef struct {
Subject base; // 继承Subject
float current_temp; // 当前温度
float threshold; // 阈值
uint32_t update_time; // 最后更新时间
} TemperatureSensor;
// 创建温度传感器主题
TemperatureSensor* temperature_sensor_create(float threshold);
// 更新温度值
void temperature_sensor_update(TemperatureSensor* sensor, float new_temp);
// 获取状态
float temperature_sensor_get_temp(TemperatureSensor* sensor);
#endif
// temperature_sensor.c
#include "temperature_sensor.h"
TemperatureSensor* temperature_sensor_create(float threshold) {
TemperatureSensor* sensor = malloc(sizeof(TemperatureSensor));
if (!sensor) return NULL;
// 初始化基类
sensor->base.observers = malloc(sizeof(ObserverInterface*) * MAX_OBSERVERS);
sensor->base.max_observers = MAX_OBSERVERS;
sensor->base.observer_count = 0;
sensor->base.context = sensor;
sensor->current_temp = 0.0f;
sensor->threshold = threshold;
sensor->update_time = 0;
return sensor;
}
void temperature_sensor_update(TemperatureSensor* sensor, float new_temp) {
if (!sensor) return;
float old_temp = sensor->current_temp;
sensor->current_temp = new_temp;
sensor->update_time = get_system_tick();
// 只有温度变化超过阈值才通知观察者
if (fabsf(new_temp - old_temp) >= sensor->threshold) {
// 准备通知数据
struct {
float temperature;
uint32_t timestamp;
float old_temperature;
} temp_data = { new_temp, sensor->update_time, old_temp };
// 通知所有观察者
subject_notify((Subject*)sensor, &temp_data);
}
}
float temperature_sensor_get_temp(TemperatureSensor* sensor) {
return sensor ? sensor->current_temp : 0.0f;
}
4. 具体观察者实现
显示观察者
// display_observer.h
#ifndef _DISPLAY_OBSERVER_H_
#define _DISPLAY_OBSERVER_H_
#include "observer.h"
typedef struct {
ObserverInterface base; // 实现观察者接口
char display_buffer[32];
uint8_t line_number;
} DisplayObserver;
DisplayObserver* display_observer_create(uint8_t line);
void display_observer_update(void* observer, Subject* subject, void* data);
#endif
// display_observer.c
#include "display_observer.h"
#include "temperature_sensor.h"
DisplayObserver* display_observer_create(uint8_t line) {
DisplayObserver* observer = malloc(sizeof(DisplayObserver));
if (!observer) return NULL;
// 设置观察者接口
observer->base.update = display_observer_update;
observer->base.destroy = NULL; // 简化实现
observer->line_number = line;
memset(observer->display_buffer, 0, sizeof(observer->display_buffer));
return observer;
}
void display_observer_update(void* observer, Subject* subject, void* data) {
DisplayObserver* disp_obs = (DisplayObserver*)observer;
TemperatureSensor* sensor = (TemperatureSensor*)subject->context;
if (data) {
// 使用传递的数据
struct { float temperature; uint32_t timestamp; }* temp_data = data;
snprintf(disp_obs->display_buffer, sizeof(disp_obs->display_buffer),
"Temp:%.1fC", temp_data->temperature);
} else {
// 直接从主题获取数据
snprintf(disp_obs->display_buffer, sizeof(disp_obs->display_buffer),
"Temp:%.1fC", sensor->current_temp);
}
// 更新显示(实际硬件操作)
lcd_display_string(disp_obs->line_number, 0, disp_obs->display_buffer);
printf("[Display] Updated: %s\n", disp_obs->display_buffer);
}
报警观察者
// alarm_observer.h
#ifndef _ALARM_OBSERVER_H_
#define _ALARM_OBSERVER_H_
#include "observer.h"
typedef struct {
ObserverInterface base;
float critical_threshold;
bool alarm_active;
} AlarmObserver;
AlarmObserver* alarm_observer_create(float threshold);
void alarm_observer_update(void* observer, Subject* subject, void* data);
#endif
// alarm_observer.c
#include "alarm_observer.h"
#include "temperature_sensor.h"
AlarmObserver* alarm_observer_create(float threshold) {
AlarmObserver* observer = malloc(sizeof(AlarmObserver));
if (!observer) return NULL;
observer->base.update = alarm_observer_update;
observer->base.destroy = NULL;
observer->critical_threshold = threshold;
observer->alarm_active = false;
return observer;
}
void alarm_observer_update(void* observer, Subject* subject, void* data) {
AlarmObserver* alarm_obs = (AlarmObserver*)observer;
TemperatureSensor* sensor = (TemperatureSensor*)subject->context;
float current_temp = sensor->current_temp;
if (current_temp >= alarm_obs->critical_threshold && !alarm_obs->alarm_active) {
// 触发报警
alarm_obs->alarm_active = true;
buzzer_start();
led_set_red();
printf("[Alarm] Critical temperature: %.1fC\n", current_temp);
} else if (current_temp < alarm_obs->critical_threshold - 2.0f && alarm_obs->alarm_active) {
// 解除报警(带滞后防止抖动)
alarm_obs->alarm_active = false;
buzzer_stop();
led_set_green();
printf("[Alarm] Temperature normal: %.1fC\n", current_temp);
}
}
数据记录观察者
// logger_observer.h
#ifndef _LOGGER_OBSERVER_H_
#define _LOGGER_OBSERVER_H_
#include "observer.h"
typedef struct {
ObserverInterface base;
char filename[32];
uint32_t log_count;
} LoggerObserver;
LoggerObserver* logger_observer_create(const char* filename);
void logger_observer_update(void* observer, Subject* subject, void* data);
#endif
// logger_observer.c
#include "logger_observer.h"
#include "temperature_sensor.h"
#include <stdio.h>
LoggerObserver* logger_observer_create(const char* filename) {
LoggerObserver* observer = malloc(sizeof(LoggerObserver));
if (!observer) return NULL;
observer->base.update = logger_observer_update;
observer->base.destroy = NULL;
strncpy(observer->filename, filename, sizeof(observer->filename)-1);
observer->log_count = 0;
return observer;
}
void logger_observer_update(void* observer, Subject* subject, void* data) {
LoggerObserver* logger = (LoggerObserver*)observer;
TemperatureSensor* sensor = (TemperatureSensor*)subject->context;
// 记录到文件(简化实现)
FILE* file = fopen(logger->filename, "a");
if (file) {
fprintf(file, "%lu,%.2f\n",
sensor->update_time, sensor->current_temp);
fclose(file);
logger->log_count++;
}
printf("[Logger] Recorded temperature: %.1fC (Total: %lu records)\n",
sensor->current_temp, logger->log_count);
}
5. 完整使用示例
// main.c
#include "temperature_sensor.h"
#include "display_observer.h"
#include "alarm_observer.h"
#include "logger_observer.h"
void setup_temperature_monitoring(void) {
// 创建温度传感器主题
TemperatureSensor* temp_sensor = temperature_sensor_create(0.5f); // 0.5°C阈值
// 创建各个观察者
DisplayObserver* display = display_observer_create(1); // 第1行显示
AlarmObserver* alarm = alarm_observer_create(85.0f); // 85°C报警
LoggerObserver* logger = logger_observer_create("temp_log.csv");
// 注册观察者
subject_attach((Subject*)temp_sensor, (ObserverInterface*)display);
subject_attach((Subject*)temp_sensor, (ObserverInterface*)alarm);
subject_attach((Subject*)temp_sensor, (ObserverInterface*)logger);
printf("Temperature monitoring system started with 3 observers\n");
// 模拟温度变化
float test_temperatures[] = {25.0f, 25.3f, 26.0f, 85.5f, 86.0f, 84.0f, 25.0f};
for (int i = 0; i < sizeof(test_temperatures)/sizeof(test_temperatures[0]); i++) {
printf("\n--- Setting temperature to %.1f°C ---\n", test_temperatures[i]);
temperature_sensor_update(temp_sensor, test_temperatures[i]);
system_delay(1000);
}
// 清理资源
subject_detach((Subject*)temp_sensor, (ObserverInterface*)display);
subject_detach((Subject*)temp_sensor, (ObserverInterface*)alarm);
subject_detach((Subject*)temp_sensor, (ObserverInterface*)logger);
free(display);
free(alarm);
free(logger);
subject_destroy((Subject*)temp_sensor);
}
int main(void) {
setup_temperature_monitoring();
return 0;
}
嵌入式观察者模式的优势
1. 解耦性
- 主题不知道观察者的具体实现
- 添加新观察者无需修改主题代码
2. 动态关系
- 观察者可随时注册/注销
- 运行时灵活调整通知关系
3. 广播通信
- 一次状态变化,多方自动响应
- 适合事件驱动架构
4. 符合开闭原则
- 对扩展开放(可添加新观察者)
- 对修改封闭(无需修改主题)
嵌入式特定优化考虑
1. 内存受限环境的优化
// 静态内存分配版本
typedef struct {
ObserverInterface* observers[MAX_OBSERVERS];
uint8_t observer_count;
} StaticSubject;
// 编译时确定观察者数组,避免动态内存分配
2. 性能优化:带过滤的通知
// 选择性通知,避免不必要的更新
void subject_notify_filtered(Subject* subject, void* data,
bool (*filter)(ObserverInterface* obs, void* data)) {
for (int i = 0; i < subject->observer_count; i++) {
if (filter(subject->observers[i], data)) {
subject->observers[i]->update(subject->observers[i], subject, data);
}
}
}
3. 实时性考虑
// 中断环境下的观察者模式
void sensor_interrupt_handler(void) {
// 在中断中只设置标志
g_sensor_data_ready = true;
}
void main_loop(void) {
if (g_sensor_data_ready) {
g_sensor_data_ready = false;
// 在主循环中处理通知,避免在中断中执行复杂逻辑
process_sensor_data_and_notify();
}
}
观察者模式vs其他模式
| 模式 | 关系 | 嵌入式示例 |
|---|---|---|
| 观察者模式 | 一对多,主题主动推送 | 传感器数据分发给多个消费者 |
| 发布-订阅模式 | 多对多,通过消息中介 | 事件总线系统 |
| 中介者模式 | 通过中介对象交互 | 复杂UI组件间的协调 |
实际应用场景
- GUI系统:按钮点击通知多个处理器
- 传感器网络:传感器数据分发给显示、存储、通信模块
- 通信协议栈:数据到达通知应用层多个协议处理器
- 状态机系统:状态变化通知相关观察者
- 调试系统:调试信息分发给串口、LCD、网络等多个输出
观察者模式是嵌入式事件驱动架构的基石,特别适合需要解耦事件产生者和消费者的场景!
更多推荐
所有评论(0)