观察者模式
观察者模式(Observer Pattern)是一种广泛应用于软件设计的行为型设计模式。在该模式中,存在两种关键的角色:
被观察者(Subject 或
Observable):这是一个包含了一系列观察者对象的集合,并提供了增加、删除观察者对象以及通知所有观察者的接口。当被观察者的状态发生变化时,它负责触发通知机制,使所有关联的观察者得到更新。观察者(Observer):这是从被观察者那里接收状态变更通知的一组类的接口或者抽象类。每个具体观察者都必须实现这个接口,以便在接收到通知时执行相应的操作。
具体流程如下:
- 观察者向被观察者注册自己,从而建立起一对多的关系。
- 当被观察者状态发生改变时,它通过调用每个观察者的更新方法来通知所有已注册的观察者。
- 每个观察者在接收到更新通知后,自行决定如何响应状态的改变。
此模式的主要优点在于降低了对象间的耦合度,使得系统的各部分更加灵活和易于复用,同时提高了系统的可扩展性。在嵌入式系统中,观察者模式可用于处理各种传感器数据更新时的通知逻辑。
具体实现
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
// 定义观察者结构体
typedef struct Observer {
void (*update)(float temperature, void *context); // 更新回调函数
void *context; // 观察者自定义上下文
} Observer;
// 定义被观察者(温度传感器)结构体
typedef struct TemperatureSensor {
float currentTemperature;
bool isChanged;
Observer *observers;
int observerCount;
void (*addObserver)(struct TemperatureSensor *, Observer *);
void (*removeObserver)(struct TemperatureSensor *, Observer *);
void (*notifyObservers)(struct TemperatureSensor *);
} TemperatureSensor;
// 添加观察者
void add_observer(TemperatureSensor *sensor, Observer *observer) {
sensor->observers = realloc(sensor->observers, (sensor->observerCount + 1) * sizeof(Observer));
sensor->observers[sensor->observerCount++] = *observer;
}
// 移除观察者
void remove_observer(TemperatureSensor *sensor, Observer *observer) {
int i;
for (i = 0; i < sensor->observerCount; i++) {
if (sensor->observers[i].update == observer->update && sensor->observers[i].context == observer->context) {
while (i < sensor->observerCount - 1) {
sensor->observers[i] = sensor->observers[i + 1];
i++;
}
sensor->observerCount--;
sensor->observers = realloc(sensor->observers, sensor->observerCount * sizeof(Observer));
break;
}
}
}
// 通知所有观察者
void notify_observers(TemperatureSensor *sensor) {
if (sensor->isChanged) {
int i;
for (i = 0; i < sensor->observerCount; i++) {
sensor->observers[i].update(sensor->currentTemperature, sensor->observers[i].context);
}
sensor->isChanged = false;
}
}
// 显示屏观察者更新函数
void display_observer_update(float temperature, void *context) {
printf("Display updated with new temperature: %.2f C\n", temperature);
}
// 报警系统观察者更新函数
void alarm_observer_update(float temperature, void *context) {
static const float ALARM_THRESHOLD = 30.0f; // 假设报警阈值为30℃
if (temperature > ALARM_THRESHOLD) {
printf("Alarm triggered! Temperature exceeds the limit of %.2f C.\n", ALARM_THRESHOLD);
}
}
// 日志记录观察者更新函数
void log_observer_update(float temperature, void *context) {
printf("Log: Temperature recorded at %.2f C.\n", temperature);
}
// 初始化温度传感器
TemperatureSensor init_temperature_sensor() {
TemperatureSensor sensor = {
.currentTemperature = 0,
.isChanged = true,
.observerCount = 0,
.addObserver = add_observer,
.removeObserver = remove_observer,
.notifyObservers = notify_observers,
.observers = NULL
};
return sensor;
}
// 主函数
int main() {
TemperatureSensor sensor = init_temperature_sensor();
// 创建观察者
Observer displayObserver = {.update = display_observer_update, .context = NULL};
Observer alarmObserver = {.update = alarm_observer_update, .context = NULL};
Observer logObserver = {.update = log_observer_update, .context = NULL};
// 注册观察者
sensor.addObserver(&sensor, &displayObserver);
sensor.addObserver(&sensor, &alarmObserver);
sensor.addObserver(&sensor, &logObserver);
// 模拟温度变化并通知观察者
sensor.currentTemperature = 25.0f;
sensor.isChanged = true;
sensor.notifyObservers(&sensor);
sensor.currentTemperature = 35.0f;
sensor.isChanged = true;
sensor.notifyObservers(&sensor);
// 清理资源
free(sensor.observers);
return 0;
}
代码解释
- 定义了观察者(Observer)结构体,包括一个更新回调函数指针update,当温度传感器的温度值发生变化时,这个函数会被调用来更新观察者(如显示屏、报警系统和日志记录器)的状态。还有一个成员变量context用来传递观察者所需的相关上下文信息。
- 定义了温度传感器(TemperatureSensor)结构体,其中包含当前温度值currentTemperature、一个布尔标志isChanged用于标记温度是否发生变化,以及用于管理观察者的数组observers、观察者数量observerCount,以及用于添加、移除观察者和通知所有观察者的函数指针。
- 实现了添加、移除观察者以及通知观察者的功能函数,如add_observer、remove_observer和notify_observers。这些函数允许温度传感器动态地添加和移除观察者,并在温度值变化时通过调用notify_observers通知所有观察者。
- 实现了三个具体观察者的更新回调函数:display_observer_update用于更新显示屏显示的温度值,alarm_observer_update用于检测并触发温度过高报警,log_observer_update用于记录温度变化的日志。
- 在主函数main中,初始化了一个温度传感器实例,创建了三个观察者实例,并将它们注册到温度传感器上。
- 在主函数main中,首先通过init_temperature_sensor函数初始化了一个温度传感器实例,该函数返回一个已经初始化的TemperatureSensor结构体,此时还未添加任何观察者。
- 然后创建了三个观察者实例,分别是displayObserver、alarmObserver和logObserver,分别对应显示屏更新、报警系统触发和日志记录的功能。每个观察者实例的update成员设置为对应的更新回调函数。
- 接下来,将这三个观察者实例通过调用add_observer函数逐一添加到温度传感器的观察者列表中。
- 在模拟温度变化的部分,先将温度设定为25℃,然后设置isChanged为true表示温度发生了变化。随后调用notify_observers函数,通知所有已注册的观察者更新其状态。此时,显示屏会显示新的温度,报警系统会判断是否触发报警(此处未触发),并且在控制台输出一条温度记录的日志。
- 继续模拟温度变化至35℃,再次进行相同的操作,这时报警系统因为温度超过了预设阈值而触发报警。
最后,在程序结束前,清理分配给温度传感器观察者列表的内存资源。
小结
上述展示了在嵌入式环境中如何利用观察者模式构建一个温度监测系统,当温度传感器的状态(温度值)发生变化时,通过观察者模式自动触发与温度相关的多种行为(如显示、报警和记录等)。这种设计方式增强了系统的灵活性和可扩展性,方便后续添加更多类型的观察者。