观察者模式的核心在于定义一个被观察者的接口,它可以注册和移除观察者,并在状态改变时通知所有观察者。同时,观察者也需要有一个接口,以便被观察者能够调用其更新方法。
下面是一个简单的C语言实现观察者模式的示例代码:
#include <stdio.h>
#include <stdlib.h>
// 观察者接口
typedef struct Observer {
void (*update)(void *data);
void *context;
} Observer;
// 被观察者接口
typedef struct Subject {
int state;
Observer **observers;
int observer_count;
int observer_capacity;
} Subject;
// 初始化被观察者
Subject *subject_new() {
Subject *subject = malloc(sizeof(Subject));
if (subject == NULL) return NULL;
subject->state = 0;
subject->observer_count = 0;
subject->observer_capacity = 5;
subject->observers = malloc(sizeof(Observer *) * subject->observer_capacity);
return subject;
}
// 注册观察者
void subject_register(Subject *subject, Observer *observer) {
if (subject->observer_count >= subject->observer_capacity) {
subject->observer_capacity *= 2;
subject->observers = realloc(subject->observers, sizeof(Observer *) * subject->observer_capacity);
}
subject->observers[subject->observer_count++] = observer;
}
// 移除观察者
void subject_unregister(Subject *subject, Observer *observer) {
for (int i = 0; i < subject->observer_count; ++i) {
if (subject->observers[i] == observer) {
// Shift all observers after the one to be removed one position to the left
memmove(&subject->observers[i], &subject->observers[i + 1], sizeof(Observer *) * (subject->observer_count - i - 1));
--subject->observer_count;
break;
}
}
}
// 通知所有观察者
void subject_notify(Subject *subject) {
for (int i = 0; i < subject->observer_count; ++i) {
subject->observers[i]->update(subject->observers[i]->context);
}
}
// 更新被观察者状态
void subject_set_state(Subject *subject, int new_state) {
subject->state = new_state;
subject_notify(subject);
}
// 观察者更新函数
void observer_update(void *data) {
printf("Observer received update with state %d\n", ((Subject *)data)->state);
}
// 清理被观察者
void subject_free(Subject *subject) {
free(subject->observers);
free(subject);
}
int main() {
Subject *subject = subject_new();
Observer observer1 = { .update = observer_update, .context = subject };
Observer observer2 = { .update = observer_update, .context = subject };
subject_register(subject, &observer1);
subject_register(subject, &observer2);
subject_set_state(subject, 1); // 通知所有观察者状态变为1
subject_unregister(subject, &observer2);
subject_set_state(subject, 2); // 只通知observer1状态变为2
subject_free(subject);
return 0;
}
在这个例子中,`Subject`结构体包含了一个动态数组`observers`来存储观察者指针,以及`observer_count`和`observer_capacity`来跟踪当前注册的观察者数量和数组的容量。`Observer`结构体则包含一个更新函数指针`update`和一个上下文`context`,这个上下文可以是任何类型的数据,通常会被传递给`update`函数。
在`main`函数中,我们创建了一个`Subject`实例,注册了两个观察者,然后更改了`Subject`的状态。每次状态改变后,`subject_notify`函数都会调用所有观察者的`update`函数,从而触发更新行为。
请注意,此代码示例假设所有观察者都有相同的上下文类型(在这个例子中是`Subject *`)。在实际应用中,你可能需要根据具体需求调整上下文类型和更新函数的参数。此外,对于生产环境中的代码,还需要确保线程安全和资源管理,例如使用互斥锁保护共享数据。