【C语言高手秘籍】C语言中观察者模式的基本实现

十年开发一朝灵 2024-11-04 17:34:45

观察者模式的核心在于定义一个被观察者的接口,它可以注册和移除观察者,并在状态改变时通知所有观察者。同时,观察者也需要有一个接口,以便被观察者能够调用其更新方法。

下面是一个简单的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 *`)。在实际应用中,你可能需要根据具体需求调整上下文类型和更新函数的参数。此外,对于生产环境中的代码,还需要确保线程安全和资源管理,例如使用互斥锁保护共享数据。

0 阅读:16

十年开发一朝灵

简介:感谢大家的关注