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

用C语言实现代理模式

代理模式(Proxy Pattern)的核心是为对象提供一个代理,通过代理控制对原对象的访问,常用于添加额外逻辑(如权限校验、缓存、远程访问等)而不修改原对象。在C语言中,可以通过结构体封装原对象指针+重写接口方法实现:代理对象实现与原对象相同的接口,内部调用原对象方法并添加控制逻辑。

C语言实现代理模式的思路

  1. 抽象主题(Subject):定义原对象和代理对象的统一接口(函数指针结构体)。
  2. 真实主题(Real Subject):实现抽象主题的核心功能(被代理的对象)。
  3. 代理(Proxy):实现抽象主题接口,内部包含真实主题的指针,在调用真实主题方法前/后添加控制逻辑(如权限检查、日志记录)。

示例:文件操作代理(添加权限校验)

假设需要一个文件读写模块,要求只有管理员权限才能写入文件,普通用户只能读取。通过代理模式在不修改原始文件操作逻辑的前提下添加权限控制。

步骤1:定义抽象主题(文件操作接口)
// 抽象主题:文件操作接口
typedef struct FileSubject {// 读取文件内容char* (*read)(struct FileSubject* self, const char* filename);// 写入文件内容int (*write)(struct FileSubject* self, const char* filename, const char* content);// 销毁对象void (*destroy)(struct FileSubject* self);
} FileSubject;
步骤2:实现真实主题(原始文件操作)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 真实主题:原始文件操作(无权限控制)
typedef struct {FileSubject subject; // 继承抽象接口
} RealFileOperator;// 原始读取逻辑:读取文件内容(简单实现)
static char* real_read(FileSubject* self, const char* filename) {FILE* file = fopen(filename, "r");if (!file) return NULL;// 获取文件大小fseek(file, 0, SEEK_END);long size = ftell(file);fseek(file, 0, SEEK_SET);// 分配内存并读取内容char* content = (char*)malloc(size + 1);if (content) {fread(content, 1, size, file);content[size] = '\0';}fclose(file);return content;
}// 原始写入逻辑:写入文件内容
static int real_write(FileSubject* self, const char* filename, const char* content) {FILE* file = fopen(filename, "w");if (!file) return 0;fputs(content, file);fclose(file);return 1; // 写入成功
}// 真实主题的销毁
static void real_destroy(FileSubject* self) {free(self); // 释放真实对象内存
}// 创建真实文件操作对象
FileSubject* real_file_operator_create() {RealFileOperator* real = (RealFileOperator*)malloc(sizeof(RealFileOperator));if (!real) return NULL;// 绑定接口方法real->subject.read = real_read;real->subject.write = real_write;real->subject.destroy = real_destroy;return (FileSubject*)real;
}
步骤3:实现代理(添加权限控制)

代理对象包含真实主题的指针,并在read/write方法中添加权限校验逻辑。

// 权限类型(用于代理控制)
typedef enum {USER_GUEST,    // 访客(只读)USER_ADMIN     // 管理员(读写)
} UserType;// 代理:带权限控制的文件操作
typedef struct {FileSubject subject;       // 继承抽象接口FileSubject* real_subject; // 指向真实主题(被代理对象)UserType user_type;        // 代理的额外属性:用户权限
} FileProxy;// 代理的读取逻辑:允许所有用户读取
static char* proxy_read(FileSubject* self, const char* filename) {FileProxy* proxy = (FileProxy*)self;printf("[代理] 用户<%d>尝试读取文件: %s\n", proxy->user_type, filename);// 调用真实主题的读取方法char* content = proxy->real_subject->read(proxy->real_subject, filename);if (content) {printf("[代理] 读取成功\n");} else {printf("[代理] 读取失败\n");}return content;
}// 代理的写入逻辑:仅管理员可写入
static int proxy_write(FileSubject* self, const char* filename, const char* content) {FileProxy* proxy = (FileProxy*)self;printf("[代理] 用户<%d>尝试写入文件: %s\n", proxy->user_type, filename);// 权限校验(代理的核心控制逻辑)if (proxy->user_type != USER_ADMIN) {printf("[代理] 权限不足:仅管理员可写入\n");return 0; // 写入失败}// 权限通过,调用真实主题的写入方法int result = proxy->real_subject->write(proxy->real_subject, filename, content);printf("[代理] 写入%s\n", result ? "成功" : "失败");return result;
}// 代理的销毁:先销毁真实主题,再释放自身
static void proxy_destroy(FileSubject* self) {FileProxy* proxy = (FileProxy*)self;proxy->real_subject->destroy(proxy->real_subject); // 销毁被代理对象free(proxy); // 释放代理对象
}// 创建文件代理(绑定真实主题和用户权限)
FileSubject* file_proxy_create(FileSubject* real_subject, UserType user_type) {if (!real_subject) return NULL;FileProxy* proxy = (FileProxy*)malloc(sizeof(FileProxy));if (!proxy) return NULL;// 绑定接口方法(重写read和write,添加控制逻辑)proxy->subject.read = proxy_read;proxy->subject.write = proxy_write;proxy->subject.destroy = proxy_destroy;// 关联真实主题和用户权限proxy->real_subject = real_subject;proxy->user_type = user_type;return (FileSubject*)proxy;
}
步骤4:使用代理模式

客户端通过代理对象访问文件,无需直接操作真实主题,权限控制逻辑由代理透明处理。

int main() {// 1. 创建真实文件操作对象(被代理)FileSubject* real_file_op = real_file_operator_create();if (!real_file_op) {printf("创建真实文件操作失败\n");return 1;}// 2. 创建访客代理(权限:只读)FileSubject* guest_proxy = file_proxy_create(real_file_op, USER_GUEST);if (!guest_proxy) {real_file_op->destroy(real_file_op);return 1;}// 访客尝试写入(预期失败)guest_proxy->write(guest_proxy, "test.txt", "访客写入的内容");// 访客尝试读取(预期成功)char* content = guest_proxy->read(guest_proxy, "test.txt");if (content) {printf("读取到内容: %s\n", content);free(content); // 释放读取的内容}// 3. 销毁访客代理(会自动销毁真实对象,需重新创建)guest_proxy->destroy(guest_proxy);// 重新创建真实对象和管理员代理real_file_op = real_file_operator_create();FileSubject* admin_proxy = file_proxy_create(real_file_op, USER_ADMIN);// 管理员尝试写入(预期成功)admin_proxy->write(admin_proxy, "test.txt", "管理员写入的内容");// 管理员尝试读取(预期成功)content = admin_proxy->read(admin_proxy, "test.txt");if (content) {printf("读取到内容: %s\n", content);free(content);}// 销毁管理员代理admin_proxy->destroy(admin_proxy);return 0;
}

输出结果

[代理] 用户<0>尝试写入文件: test.txt
[代理] 权限不足:仅管理员可写入
[代理] 用户<0>尝试读取文件: test.txt
[代理] 读取失败
[代理] 用户<1>尝试写入文件: test.txt
[代理] 写入成功
[代理] 用户<1>尝试读取文件: test.txt
[代理] 读取成功
读取到内容: 管理员写入的内容

核心思想总结

  1. 控制访问:代理通过在调用真实对象方法前添加逻辑(如权限校验),实现对原对象的访问控制,且不修改原对象代码。
  2. 透明性:代理与真实对象实现相同的FileSubject接口,客户端无需区分,可无缝切换。
  3. 功能扩展:除权限控制外,代理还可添加缓存(重复读取时返回缓存内容)、日志记录、远程访问(代理作为本地对象,实际调用远程服务)等功能。

C语言通过结构体封装真实对象指针和额外属性(如user_type),结合函数指针重写实现了代理模式的核心,适合需要在不侵入原逻辑的前提下增强对象功能的场景。

http://www.dtcms.com/a/506666.html

相关文章:

  • 云开发CloudBase AI+实战:快速搭建AI小程序全流程指南
  • ESP32学习笔记(基于IDF):连接手机热点,用TCP协议实现数据双向通信
  • 一个小程序轻量AR体感游戏,开发实现解决方案
  • java整合itext pdf实现固定模版pdf导出
  • 26考研数学一、二、三真题试卷及答案PDF电子版(1987-2025年)
  • Django Web 开发系列(二):视图进阶、快捷函数与请求响应处理
  • 重庆哪些网站推广公司wordpress获取用户名
  • Bevy 渲染系统 Bindless 实现与交互逻辑
  • K8s控制器终极对比:StatefulSet与Deployment详解
  • [Agent可视化] docs | go/rust/py混构 | Temporal编排 | WASI沙箱
  • Linux服务器编程实践55-网络信息API:gethostbyname与gethostbyaddr实现主机名解析
  • Godot 2D游戏开发全流程实战
  • 自动驾驶工程师面试(定位、感知向)
  • Cocos学习——摄像机Camera
  • 千秋网站建设公司百度如何快速收录
  • 深圳大型论坛网站建设免费行情网站在线
  • 《软件测试分类指南(下):从测试阶段到地域适配,拆解落地核心维度》
  • Python 查询网站开发3g小说网站
  • 基于Python的Word文档模板自动化处理:从占位符提取到智能填充
  • vue3子组件向父组件传递参数
  • 阿里云云代理商:阿里云CDN刷新机制是什么?
  • FFmpeg 基本数据结构 AVFormatConext 分析
  • 使用 DrissionPage——实现同花顺股票数据自动化爬虫
  • 基于位置式PID算法调节PWM占空比实现电机转速控制
  • FFmpeg+QT输出音频
  • 友点企业网站管理系统微信商城在哪里找
  • 深度学习(5)-PyTorch 张量详细介绍
  • 西安市建设厅网站软文营销的经典案例
  • Agent 开发设计模式(Agentic Design Patterns )第8章: 智能体记忆管理(Memory Management)
  • Linux 下使用 Docker-Compose 安装 Kafka 和 Kafka-UI(KRaft 模式)