当前位置: 首页 > news >正文

观察者模式说明(C语言版本)

观察者模式主要是为了实现一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。下面使用C语言实现了一个具体的应用示例,有需要的可以参考下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

// 观察者的结构定义
typedef struct {
    void (*add)(void *data);
    void (*update)(void *data);
    void (*delete)(void *data);
} observer_t;

// 观察者链表节点定义
typedef struct _observer_list_t {
    observer_t *observer;
    struct _observer_list_t *next;
} observer_list_t;

// 被观察者定义
typedef struct _subject_t {
    void *data;
    observer_list_t *observer; // 观察者链表
} subject_t;

// 初始化观察者的更新函数
void init_observer_update(observer_t *observer, void (*update)(void *data)) {
    observer->update = update;
}

// 初始化观察者的添加函数
void init_observer_add(observer_t *observer, void (*add)(void *data)) {
    observer->add = add;
}

// 初始化观察者的删除函数
void init_observer_delete(observer_t *observer, void (*delete)(void *data)) {
    observer->delete = delete;
}

// 加入观察者队列
bool attach_observer(subject_t *subject, observer_t *observer) {
    observer_list_t *node = (observer_list_t *)malloc(sizeof(observer_list_t));
    if (!node) return false; // 内存分配失败

    node->observer = observer;
    node->next = subject->observer;
    subject->observer = node;
    return true;
}

// 从观察者队列删除
bool detach_observer(subject_t *subject, observer_t *observer) {
    observer_list_t *node = subject->observer;
    observer_list_t *prev = NULL;

    while (node) {
        if (node->observer == observer) {
            if (prev) {
                prev->next = node->next;
            } else {
                subject->observer = node->next;
            }
            free(node);
            return true;
        }
        prev = node;
        node = node->next;
    }
    return false; // 未找到观察者
}

// 修改被观察数据
void set_observer_data(subject_t *subject, void *value) {
    subject->data = value;
}

// 通知观察者更新
void notify_observer_update(subject_t *subject) {
    observer_list_t *node = subject->observer;
    int count = 0;
    for (; node; node = node->next) {
        printf("Notify observer update %d. Data: %s\n", count, (char *)subject->data);
        count++;
        if (node->observer->update) {
            node->observer->update(subject->data);
        }
    }
}

// 通知观察者添加(这个在实际应用中可能不常见,通常只通知更新或删除)
void notify_observer_add(subject_t *subject) {
    // ...(类似notify_observer_update,但调用add函数)
    // 这里为了简洁省略,实际应用中根据需要实现
}

// 通知观察者删除(同样,这个在标准观察者模式中不常见)
void notify_observer_delete(subject_t *subject) {
    // ...(类似notify_observer_update,但调用delete函数)
    // 这里为了简洁省略,实际应用中根据需要实现
}

// 初始化主题对象
void init_subject(subject_t *subject) {
    memset(subject, 0, sizeof(subject_t));
}

// 释放主题对象及其所有观察者
void free_subject(subject_t *subject) {
    observer_list_t *node = subject->observer;
    while (node) {
        observer_list_t *temp = node;
        node = node->next;
        free(temp);
    }
    // 注意:这里没有释放subject->data,因为不清楚其分配方式。在实际应用中需要适当处理。
}

使用示例

// 假设我们有一个简单的字符串观察者,它会打印接收到的字符串
void observer_update(void *data) {
    printf("Observer received update: %s\n", (char *)data);
}

int main() {
    // 创建一个主题对象
    subject_t subject;
    init_subject(&subject);

    // 创建一个观察者并初始化其更新函数
    observer_t observer;
    init_observer_update(&observer, observer_update);

    // 将观察者附加到主题对象
    attach_observer(&subject, &observer);

    // 设置被观察数据并通知观察者
    set_observer_data(&subject, "Hello, Observer!");
    notify_observer_update(&subject);

    // 从主题对象中删除观察者
    detach_observer(&subject, &observer);

    // 释放主题对象(在实际应用中,通常在程序结束时进行)
    free_subject(&subject);

    return 0;
}

执行结果

在这里插入图片描述

相关文章:

  • 达梦:dmserver占用io高排查
  • Kubernetes知识点总结(十)
  • C#之上位机开发---------C#通信库及WPF的简单实践
  • 初学PADS使用技巧笔记(也许会继续更新)
  • IDEA单元测试插件 SquareTest 延长试用期权限
  • 【python】向Jira推送自动化用例执行成功
  • 2025年-G4--lc75--Best Time to Buy and Sell Stock(java版)
  • 人工智能神经网络
  • Ollama+DeepSeek+Open-WebUi
  • 在自有ARM系统上离线安装MongoDB的坎坷历程与解决方案
  • 云贝餐饮连锁V3独立版全开源+vue源码
  • Vue前端开发-Vant介绍,安装部署
  • 使用 Apache PDFBox 提取 PDF 中的文本和图像
  • deepseek_各个版本django特性
  • Python如何播放本地音乐并在web页面播放
  • C#的委托delegate与事件event
  • es6的Generator函数用法
  • 【Git】reflog实战:找回丢失的提交
  • USB2.03.0接口区分usb top工具使用
  • uniapp 打包安卓 集成高德地图
  • 人民日报今日谈:科技赋能,继续把制造业搞好
  • 上海乐高乐园客流预测来了:工作日0.8万人次/日,周末节假日2万人次/日
  • 习近平:推进中国式现代化要继续把制造业搞好
  • 自然资源部:适应存量时代城市更新发展,严控增量盘活存量
  • 住建部:我国超9.4亿人生活在城镇
  • 特朗普与泽连斯基通话