观察者模式的核心思想

观察者模式(Observer Pattern),这是在嵌入式系统中极其重要且广泛应用的一种行为型设计模式。

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

简单比喻

  • 主题(Subject):就像微信公众号平台
  • 观察者(Observer):就像订阅公众号的用户
  • 通知机制:公众号发布新文章时,所有订阅者自动收到推送

观察者模式解决的嵌入式问题

典型问题场景

  1. 传感器数据分发:一个温度传感器数据变化,需要同时通知显示屏、报警器、数据记录器
  2. 事件处理:按键按下事件需要同时触发界面更新、业务逻辑、声音反馈
  3. 状态监控:电池电量变化需要通知功耗管理、UI显示、预警系统
  4. 通信消息:收到网络数据包需要分发给多个处理模块

传统做法的困境

// 紧耦合的实现方式(不推荐)
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组件间的协调

实际应用场景

  1. GUI系统:按钮点击通知多个处理器
  2. 传感器网络:传感器数据分发给显示、存储、通信模块
  3. 通信协议栈:数据到达通知应用层多个协议处理器
  4. 状态机系统:状态变化通知相关观察者
  5. 调试系统:调试信息分发给串口、LCD、网络等多个输出

观察者模式是嵌入式事件驱动架构的基石,特别适合需要解耦事件产生者和消费者的场景!

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐