在嵌入式系统开发中,组件间的通信和状态同步是系统设计的关键挑战,观察者模式(Observer Pattern)通过定义对象间的一对多依赖关系,为这一问题提供了优雅的解决方案,使得系统各个组件能够高效地响应状态变化和事件通知。

观察者模式的核心概念

观察者模式是一种行为设计模式,它定义了一种一对多的依赖关系,当一个对象(主题)的状态发生改变时,所有依赖于它的对象(观察者)都会得到通知并自动更新。

嵌入式系统中的观察者模式应用

  1. 事件通知系统

在嵌入式系统中,硬件事件(如中断、定时器到期)需要被多个软件组件处理,观察者模式提供了理想的解决方案。

// 系统事件类型定义
typedef enum {
    EVENT_BUTTON_PRESS,
    EVENT_BUTTON_RELEASE,
    EVENT_TIMER_EXPIRED,
    EVENT_SENSOR_DATA_READY,
    EVENT_NETWORK_CONNECTED,
    EVENT_NETWORK_DISCONNECTED,
    EVENT_BATTERY_LOW,
    EVENT_SYSTEM_ERROR
} system_event_t;

// 事件数据结构
typedef struct {
    system_event_t type;
    uint32_t timestamp;
    void *data;
    size_t data_size;
} event_t;
  1. 传感器数据分发

多个应用组件可能需要同时监听同一个传感器的数据更新。

// 传感器数据类型
typedef struct {
    float temperature;
    float humidity;
    float pressure;
    uint32_t sequence;
} sensor_data_t;

// 传感器更新观察者
typedef struct {
    void (*on_temperature_update)(float temperature);
    void (*on_humidity_update)(float humidity);
    void (*on_pressure_update)(float pressure);
    void (*on_sensor_error)(sensor_error_t error);
} sensor_observer_t;
  1. 系统状态监控 系统关键状态(如电池电量、网络连接状态)的变化需要被多个模块感知。

// 系统状态类型
typedef enum {
    SYSTEM_STATE_NORMAL,
    SYSTEM_STATE_WARNING,
    SYSTEM_STATE_CRITICAL,
    SYSTEM_STATE_EMERGENCY
} system_state_t;

// 状态变化观察者
typedef struct {
    void (*on_state_changed)(system_state_t new_state, system_state_t old_state);
    void (*on_battery_level)(uint8_t level);
    void (*on_memory_usage)(uint32_t used, uint32_t total);
} system_observer_t;

我们可以实现一个轻量级的自定义事件总线:

// 事件总线实现
typedef struct observer_node {
    void (*callback)(void *data);        // 观察者回调函数
    void *context;                       // 观察者上下文
    struct observer_node *next;          // 下一个观察者
} observer_node_t;

typedef struct {
    observer_node_t *observers;          // 观察者链表
    uint8_t event_id;                    // 事件ID
} event_bus_t;

static event_bus_t event_bus[MAX_EVENTS];
static uint8_t event_count = 0;

// 初始化事件总线
void event_bus_init(void) {
    for(int i = 0; i < MAX_EVENTS; i++) {
        event_bus[i].observers = NULL;
    }
    event_count = 0;
}

// 注册事件观察者
bool event_bus_register(uint8_t event_id, void (*callback)(void *), void *context) {
    if(event_id >= MAX_EVENTS || callback == NULL) {
        returnfalse;
    }
    
    // 创建新的观察者节点
    observer_node_t *new_observer = malloc(sizeof(observer_node_t));
    if(new_observer == NULL) {
        returnfalse;
    }
    
    new_observer->callback = callback;
    new_observer->context = context;
    new_observer->next = NULL;
    
    // 添加到观察者链表
    if(event_bus[event_id].observers == NULL) {
        event_bus[event_id].observers = new_observer;
    } else {
        observer_node_t *current = event_bus[event_id].observers;
        while(current->next != NULL) {
            current = current->next;
        }
        current->next = new_observer;
    }
    
    returntrue;
}

// 发布事件
void event_bus_publish(uint8_t event_id, void *data) {
    if(event_id >= MAX_EVENTS) {
        return;
    }
    
    observer_node_t *current = event_bus[event_id].observers;
    while(current != NULL) {
        // 调用观察者回调函数
        if(current->callback != NULL) {
            current->callback(data);
        }
        current = current->next;
    }
}

// 取消注册观察者
bool event_bus_unregister(uint8_t event_id, void (*callback)(void *)) {
    if(event_id >= MAX_EVENTS || callback == NULL) {
        returnfalse;
    }
    
    observer_node_t *current = event_bus[event_id].observers;
    observer_node_t *previous = NULL;
    
    while(current != NULL) {
        if(current->callback == callback) {
            // 从链表中移除
            if(previous == NULL) {
                event_bus[event_id].observers = current->next;
            } else {
                previous->next = current->next;
            }
            free(current);
            returntrue;
        }
        previous = current;
        current = current->next;
    }
    
    returnfalse;
}

观察者模式在嵌入式中的优势

  1. 解耦组件依赖

传统的直接调用方式:

// 紧耦合的实现
void sensor_data_ready(int temperature, int humidity) {
    update_display(temperature, humidity);  // 直接调用显示模块
    write_to_log(temperature, humidity);    // 直接调用日志模块
    check_alerts(temperature, humidity);    // 直接调用告警模块
}

观察者模式方式:

// 松耦合的实现
void sensor_data_ready(int temperature, int humidity) {
    sensor_data_t data = {temperature, humidity};
    event_bus_publish(EVENT_SENSOR_DATA, &data);  // 发布事件,不关心谁接收
}
  1. 动态注册机制

观察者可以在运行时动态注册和注销:

// 运行时注册观察者
void system_startup(void) {
    // 正常模式注册所有观察者
    event_bus_register(EVENT_SENSOR_DATA, display_update_handler, &display);
    event_bus_register(EVENT_SENSOR_DATA, logging_handler, &logger);
    event_bus_register(EVENT_SENSOR_DATA, alert_handler, &alerts);
}

void enter_low_power_mode(void) {
    // 低功耗模式下只保留必要的观察者
    event_bus_unregister(EVENT_SENSOR_DATA, display_update_handler);
    event_bus_unregister(EVENT_SENSOR_DATA, logging_handler);
    // alert_handler 继续接收事件
}
  1. 灵活的事件过滤

观察者可以根据需要选择监听特定事件:

// 选择性事件监听
PROCESS_THREAD(selective_observer_process, ev, data) {
    PROCESS_BEGIN();
    
    while(1) {
        PROCESS_WAIT_EVENT();
        
        // 只处理感兴趣的事件
        switch(ev) {
            case EVENT_SENSOR_DATA:
                if(((sensor_data_t*)data)->temperature > 30) {
                    handle_high_temperature((sensor_data_t*)data);
                }
                break;
                
            case EVENT_BUTTON_PRESS:
                handle_button_press();
                break;
                
            // 忽略其他事件
            default:
                break;
        }
    }
    
    PROCESS_END();
}

总结

观察者模式在嵌入式系统中展现了强大的事件处理能力,它不仅解决了组件间通信的耦合问题,还提供了高度的灵活性和清晰的架构。

通过合理的设计和优化,观察者模式可以在不牺牲系统性能的前提下,显著提升代码的可维护性和系统的可靠性,是嵌入式软件架构中不可或缺的设计模式之一。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“星球”加入知识星球,有问必答。
点击“阅读原文”查看知识星球详情,欢迎点分享、收藏、点赞、在看。
Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐