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

C++设计模式之结构型模式:代理模式(Proxy)

代理模式(Proxy)是结构型设计模式的一种,它通过提供一个替代对象来控制对原对象的访问,常用于在不改变原对象的前提下,为其添加额外功能(如权限控制、延迟加载、日志记录等)。这种模式类似于现实生活中的“代理人”或“中介”,客户端通过代理与目标对象交互。

一、核心思想与角色

代理模式的核心是“控制访问,增强功能”,通过引入代理对象,在客户端与目标对象之间建立一层中间层。其核心角色如下:

角色名称核心职责
抽象主题(Subject)定义目标对象和代理对象的共同接口,确保代理可替代目标对象。
真实主题(RealSubject)实现抽象主题接口,是被代理的真实对象,包含核心业务逻辑。
代理(Proxy)实现抽象主题接口,内部持有真实主题的引用,在调用真实主题方法前后添加额外逻辑(如权限校验)。
客户端(Client)通过抽象主题接口与代理交互,无需知道代理背后是否是真实对象。

核心思想:代理与真实对象实现相同接口,客户端无需区分两者;代理在转发请求的同时,可添加额外操作,实现对真实对象的访问控制和功能增强。

二、实现示例(图片加载代理)

假设我们需要加载大型图片(如高清图片),直接加载可能消耗大量资源且耗时。使用代理模式可实现“延迟加载”(仅在需要显示时才真正加载图片),并添加日志记录功能:

#include <iostream>
#include <string>// 1. 抽象主题(Subject):图片
class Image {
public:virtual void display() const = 0; // 显示图片virtual ~Image() = default;
};// 2. 真实主题(RealSubject):高清图片
class HighResolutionImage : public Image {
private:std::string filename; // 图片文件名// 真实加载图片(耗时操作)void loadFromDisk() const {std::cout << "从磁盘加载高清图片:" << filename << std::endl;}public:HighResolutionImage(const std::string& name) : filename(name) {// 构造函数不加载图片(延迟到display时)}// 显示图片(实际加载并显示)void display() const override {loadFromDisk(); // 真实加载std::cout << "显示高清图片:" << filename << std::endl;}
};// 3. 代理(Proxy):图片代理
class ImageProxy : public Image {
private:HighResolutionImage* realImage; // 真实图片对象(延迟初始化)std::string filename;           // 图片文件名std::string userRole;           // 用户角色(用于权限控制)// 检查权限bool hasPermission() const {return userRole == "admin" || userRole == "viewer";}public:// 构造函数:仅存储文件名和用户角色,不创建真实对象ImageProxy(const std::string& name, const std::string& role): realImage(nullptr), filename(name), userRole(role) {}// 显示图片:代理控制逻辑void display() const override {// 1. 权限校验if (!hasPermission()) {std::cout << "权限不足:用户" << userRole << "无法查看图片" << std::endl;return;}// 2. 延迟加载:仅在需要时创建真实对象if (!realImage) {realImage = new HighResolutionImage(filename);std::cout << "代理:创建真实图片对象" << std::endl;}// 3. 日志记录std::cout << "代理:记录图片访问 - " << filename << std::endl;// 4. 调用真实对象的方法realImage->display();}// 析构函数:释放真实对象~ImageProxy() override {delete realImage;}
};// 客户端代码:通过代理访问图片
int main() {// 1. 无权限用户访问Image* proxy1 = new ImageProxy("vacation.jpg", "guest");std::cout << "=== 游客访问 ===" << std::endl;proxy1->display();// 2. 有权限用户访问(首次加载)Image* proxy2 = new ImageProxy("vacation.jpg", "viewer");std::cout << "\n=== 查看者首次访问 ===" << std::endl;proxy2->display();// 3. 有权限用户再次访问(复用真实对象)std::cout << "\n=== 查看者再次访问 ===" << std::endl;proxy2->display();// 释放资源delete proxy1;delete proxy2;return 0;
}

三、代码解析

  1. 抽象主题(Image):定义了display()接口,是真实图片和代理的共同基类,确保代理可替代真实对象。

  2. 真实主题(HighResolutionImage):实现了高清图片的核心功能,loadFromDisk()是耗时操作(模拟大型图片加载),display()负责实际显示。

  3. 代理(ImageProxy)

    • 权限控制hasPermission()检查用户是否有权限访问图片,无权限则拒绝请求。
    • 延迟加载:仅在首次调用display()且有权限时,才创建HighResolutionImage对象,避免不必要的资源消耗。
    • 日志记录:在调用真实对象方法前记录访问日志。
    • 转发请求:最终调用真实对象的display()方法,完成核心功能。
  4. 客户端使用:客户端通过Image接口与代理交互,无需知道是否使用了代理,实现了对真实对象的透明访问。

四、常见代理类型与适用场景

代理模式有多种变体,根据功能不同可分为:

代理类型核心功能适用场景
远程代理为远程对象(如网络服务)提供本地代理,隐藏网络通信细节。分布式系统、RPC框架
虚拟代理延迟创建开销大的对象(如示例中的延迟加载),优化性能。大型图片加载、复杂对象初始化
保护代理控制对真实对象的访问,验证权限或过滤请求。权限管理、敏感操作保护
智能引用代理在访问对象时添加额外操作(如计数引用、自动释放、日志记录)。资源管理、调试日志
缓存代理缓存真实对象的结果,重复请求直接返回缓存,减少计算或网络开销。数据库查询缓存、API结果缓存

五、核心优势与与其他模式的区别

优势
  1. 功能增强:在不修改真实对象的前提下,为其添加额外功能(如日志、权限),符合开闭原则。
  2. 控制访问:可限制对真实对象的访问(如权限校验),保护敏感资源。
  3. 优化性能:通过延迟加载、缓存等机制,减少不必要的资源消耗。
  4. 隐藏细节:如远程代理隐藏网络通信细节,客户端无需关心对象位置。
与其他模式的区别
模式核心差异点
代理模式控制对对象的访问,添加额外功能,代理与真实对象实现同一接口,强调“访问控制”。
装饰器模式动态为对象添加功能,不控制访问,装饰器通常嵌套使用,强调“功能扩展”。
适配器模式转换接口使不兼容的类协作,不改变原功能,强调“接口适配”。
外观模式为复杂子系统提供简化接口,不针对单个对象,强调“简化使用”。

六、实践建议

  1. 接口一致性:代理必须与真实对象实现相同接口,确保客户端透明使用。
  2. 单一职责:一个代理应专注于一种功能(如要么做权限控制,要么做缓存),避免设计复杂的“万能代理”。
  3. 延迟初始化:对开销大的真实对象,通过代理实现延迟创建,优化系统启动速度。
  4. 避免过度使用:简单场景下直接使用真实对象更高效,无需引入代理增加复杂性。

代理模式的核心价值在于“在不侵入原对象的前提下,灵活控制访问并增强功能”。它通过引入中间层,实现了客户端与真实对象的解耦,同时为系统扩展提供了便利。在需要权限控制、性能优化或功能增强的场景中,代理模式是一种优雅的解决方案。

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

相关文章:

  • 八股已死、场景当立(分布式ID篇)
  • C++指针笔试题1
  • 中英双语 网站 模板网站建设项目验收单
  • 【centos生产环境搭建(二)redis安装】
  • 四川移动网站建设网架报价明细表
  • 网站设计思路WordPress客户端
  • 做试玩网站网站快速排名技术
  • Day30_【NLP 自然语言处理(0)—入门】
  • springboot 配置 HikariDataSource 连接池信息
  • identity mapping kernel image mapping
  • Docker操作命令
  • iOS 26 能耗检测实战指南,升级后电池掉速是否正常 + KeyMob + Instruments 实时监控 + 优化策略
  • perl踩坑系列===正则表达式第2坑---split中的“或”操作符
  • 苹果iOS 26正式版系统性能深度测试:续航、信号、流畅度详细解析
  • 假网站网站怎么做中山中小企业网站建设
  • 网站备案 二级域名学会网站建设项目
  • 01-元字符:如何巧妙记忆正则表达式的基本元件?
  • yandex俄语网站建设广东省网站备案查询
  • nginx xxs漏铜修复、nginx 域名配置、nginx https证书配置、Http不安全处理方法
  • 建设银行客户端官方网站flask做大型网站开发
  • 耐达讯自动化妙解Modbus与Profibus协议冲突:变频器控制的“黄金公式“
  • 自动化专业核心课《计算机控制技术》导览---数字时代的控制中枢
  • 【星海出品】计算机科学缓存命中学习
  • YOLO入门教程(番外):计算机视觉数学、编程基础
  • 做商品网站医院网站建设方案计划书
  • 从零开始学RabbitMQ:Java实战简单模式与工作队列消息处理
  • 农家乐网站模板腾讯云电商网站建设
  • 响应式网站用什么软件做效果站酷设计网站官网入口免费个人海报
  • JavaScript中国手机号校验
  • 【OJ】stack 的经典OJ题