当前位置: 首页 > 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;
}

执行结果

在这里插入图片描述

相关文章:

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

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

LeetCode 230.二叉搜索树中第K小的元素

题目&#xff1a;给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 小的元素&#xff08;从 1 开始计数&#xff09;。 思路&#xff1a; 代码&#xff1a; /*** Definition for a binary tree node.* public class Tre…...

11、集合框架

一、简介 Java集合框架位于java.util包中 Collection是Set和List的父类&#xff0c;Collections是工具类&#xff0c;提供了对集合进行排序、遍历等多种算法的实现。 ArrayList: 有序(放进去顺序和拿出来顺序一致)&#xff0c;可重复 HashSet: 无序(放进去顺序和拿出来顺序不…...

git常用指令详解

文章目录 Git 基本指令的使用Git 远程仓库Git的分支管理 Git 基本指令的使用 git init //初始化一个git仓库,在当前目录下生成.git文件夹&#xff0c;并且会默认生成一个master分支。git clone <url> [directory] //url为git仓库地址&#xff0c;directory为本地目录 gi…...

Debezium 报错:“The db history topic is missing” 的处理方法

Debezium 报错:“The db history topic is missing” 的处理方法 一、引言 在使用 Debezium 进行数据同步时,可能会遇到一个常见的错误:“The db history topic is missing”。这个错误表明 Debezium 无法找到或访问其数据库历史记录主题(db history topic),这通常是由…...

Grok 3.0 Beta 版大语言模型评测

2025年2月17日至18日&#xff0c;全球首富埃隆马斯克&#xff08;Elon Musk&#xff09;携手其人工智能公司xAI&#xff0c;在美国重磅发布了Grok 3.0 Beta版。这款被誉为“迄今为止世界上最智能的语言模型”的AI&#xff0c;不仅集成了先进的“DeepSearch”搜索功能&#xff0…...

AcWing 3691:有向树形态 ← 卡特兰数 + 复旦大学考研机试题

【题目来源】 https://www.acwing.com/problem/content/3694/ 【题目描述】 求 N 个相同结点能够组成的二叉树的个数。 【输入格式】 一个整数 N。 【输出格式】 输出能组成的二叉树的个数。 【数据范围】 1≤N≤20 【输入样例】 3 【输出样例】 5 【算法分析】 ● 卡特…...

便携式动平衡仪Qt应用层详细设计方案(基于Qt Widgets)

便携式动平衡仪Qt应用层详细设计方案&#xff08;基于Qt Widgets&#xff09; 版本&#xff1a;1.0 日期&#xff1a;2023年10月 一、系统概述 1.1 功能需求 开机流程&#xff1a;长按电源键启动&#xff0c;全屏显示商标动画&#xff08;快闪3~4次&#xff09;。主界面&…...

SpringBoot源码解析(十一):准备应用上下文

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args Sp…...

CSS 使用white-space属性换行

一、white-space属性的常见值 * 原本格式&#xff1a; 1、white-space:normal 默认值&#xff0c;空格和换行符会被忽略过滤掉&#xff1b;宽度不够时文本会自动换行 * 宽度足够时&#xff0c;normal 处理后的格式 * 宽度不够时&#xff0c; normal 处理后的格式 2、white-spa…...

论文笔记(七十二)Reward Centering(四)

Reward Centering&#xff08;四&#xff09; 文章概括摘要附录A 伪代码 文章概括 引用&#xff1a; article{naik2024reward,title{Reward Centering},author{Naik, Abhishek and Wan, Yi and Tomar, Manan and Sutton, Richard S},journal{arXiv preprint arXiv:2405.09999…...

Matlab——图像保存导出成好看的.pdf格式文件

点击图像的右上角&#xff0c;点击第一个保存按钮键。...

官方文档学习TArray容器

一.TArray中的元素相等 1.重载一下 元素中的 运算符&#xff0c;有时需要重载排序。接下来&#xff0c;我们将id 作为判断结构体的标识。 定义结构体 USTRUCT() struct FXGEqualStructInfo {GENERATED_USTRUCT_BODY() public:FXGEqualStructInfo(){};FXGEqualStructInfo(in…...

unxi-进程间通信

1.进程间通信实现方式 【1】同一主机 linux下通信方式: a.传统的进程间通信方式 管道 --- 进行数据传输的"管道" 无名管道 有名管道 信号 --- b.system v 进程间通信 (posix 进程间通信) 共享内存 (进程间…...

微型分组加密算法TEA、XTEA、XXTEA

微型分组加密算法TEA、XTEA、XXTEA TEA&#xff08;Tiny Encryption Algorithm&#xff09;算法是一种分组加密算法&#xff0c;由剑桥大学计算机实验室的‌David Wheeler和‌Roger Needham于1994年发明。TEA、XTEA、XXTEA算法采用64位的明文分组和128位的密钥。它使用Feistel…...

conda 基本命令

1、查询当前所有的环境 conda env list 2、创建虚拟环境 conda create -n 环境名 [pythonpython版本号] 其中[pythonpython版本号]可以不写 conda create -n test python3.12 我们输入conda env list看到我们的环境创建成功了&#xff0c;但是发现他是创建在我们默认的C盘的…...

详解 为什么 tcp 会出现 粘包 拆包 问题

TCP 会出现 粘包 和 拆包 问题&#xff0c;主要是因为 TCP 是 面向字节流 的协议&#xff0c;它不关心应用层发送的数据是否有边界&#xff0c;也不会自动分割或合并数据包。由于 TCP 的流控制和传输机制&#xff0c;数据可能在传输过程中被拆分成多个小的 TCP 包&#xff0c;或…...

Linus的基本命令

以下是一些常见的 Linux 命令&#xff1a; 一、文件和目录操作&#xff1a; - ls&#xff1a;列出目录中的文件和子目录&#xff0c;常用参数有 -a &#xff08;显示所有文件&#xff0c;包括隐藏文件&#xff09;、 -l &#xff08;显示详细信息&#xff09;、 -h &#xff0…...

【Linux】缓冲区和文件系统

个人主页~ 缓冲区和文件系统 一、FILE结构1、fd2、缓冲区&#xff08;一&#xff09;有换行有return全部打印&#xff08;二&#xff09;无换行无return的C接口打印&#xff08;三&#xff09;无换行无return的系统调用接口打印&#xff08;四&#xff09;有换行无return的C接口…...

函数式编程:概念、特性与应用

1. 函数式编程简介 函数式编程&#xff0c;从名称上看就与函数紧密相关。它是一种我们常常使用却可能并未意识到的编程范式&#xff0c;关注代码的结构组织&#xff0c;强调一个纯粹但在实际中有些理想化的不可变世界&#xff0c;涉及数学、方程和副作用等概念&#xff0c;甚至…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...

Vue 实例的数据对象详解

Vue 实例的数据对象详解 在 Vue 中,数据对象是响应式系统的核心,也是组件状态的载体。理解数据对象的原理和使用方式是成为 Vue 专家的关键一步。我将从多个维度深入剖析 Vue 实例的数据对象。 一、数据对象的定义方式 1. Options API 中的定义 在 Options API 中,使用 …...

基于Java项目的Karate API测试

Karate 实现了可以只编写Feature 文件进行测试,但是对于熟悉Java语言的开发或是测试人员,可以通过编程方式集成 Karate 丰富的自动化和数据断言功能。 本篇快速介绍在Java Maven项目中编写和运行测试的示例。 创建Maven项目 最简单的创建项目的方式就是创建一个目录,里面…...