设计模式-04 设计模式-Proxy Pattern 代理模式

embedded/2024/11/17 7:25:04/
设计模式-04 设计模式-Proxy Pattern 代理模式
 

1.定义

代理模式 为一个对象提供一个代理或占位符,以便控制对该对象的访问和操作。代理可以拦截并修改对目标对象的调用,从而实现以下目的:

控制访问:限制对敏感或昂贵对象的访问,只允许经过身份验证或授权的用户访问。
延迟实例化:推迟创建昂贵或耗时的对象,直到真正需要时才创建。
提供额外的功能(日志记录,监控):在不修改目标对象的情况下,向目标对象添加额外的功能,例如日志记录、缓存或安全检查。
缓存功能:对于昂贵的对象,可以减少重复创建,减少调用真实对象的次数

       

+--------------+|              ||   Interface  ||              |+--------------+|v+--------------+            +--------------+|   Proxy       |  ----|>   |   Concrete   ||   Object      |           |  Object      |+--------------+            +--------------+
2.内涵

代理模式 结构,代理模式包含以下角色:

  • Subject(目标):被代理的真实对象。
  • Proxy(代理):提供对目标对象的代理或占位符。
  • Client(客户端):使用代理来访问目标对象。

常用例子:

一个代理模式的例子是远程代理,它可以代表远程服务器上的对象。远程代理拦截对本地对象的调用,并将其转发到远程服务器上的实际对象。这允许客户端与远程对象交互,而无需直接访问远程服务器。

此外开源软件里面用的此模式的场景:

  • Mockito:使用代理模式创建模拟对象,用于单元测试。
  • Javassist:使用代理模式动态生成字节码,用于增强和修改现有类。
  • ASM:使用代理模式在字节码级别增强和修改类。
3.案例

一个简单使用 代理模式的c++ demo 

#include <iostream>using namespace std;class Image {
public:virtual void display() = 0;
};class RealImage : public Image {
private:std::string filename;public:RealImage(const std::string& filename) : filename(filename) {std::cout << "加载 image: " << filename << std::endl;}void display() override {std::cout << "显示 image: " << filename << std::endl;}
};class ImageProxy : public Image {
private:RealImage* realImage;std::string filename;public:ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}void display() override {if (nullptr == realImage) {realImage = new RealImage(filename);  // 如果有加载这次就不加载}realImage->display();}
};int main() {Image* image = new ImageProxy("example.jpg");image->display(); // 具有缓存功能image->display();delete image; // Clean upreturn 0;
}
4.最佳实践


代理模式最佳实践:

明确代理目的:清楚地定义代理的职责和它要解决的问题。
将代理与目标对象解耦:代理不应该直接依赖于目标对象的具体实现。使用抽象接口或基类来表示目标对象,以便代理可以与不同的目标对象一起使用。
保持代理与目标对象同步:如果目标对象的状态发生变化,代理也应该相应地更新。
避免代理循环:确保代理不会直接或间接地引用自身,否则会导致无限循环。
使用虚拟代理来延迟实例化:只在需要时才创建目标对象,以提高性能。
考虑使用 AOP(面向方面编程):AOP 框架可以简化代理的创建和管理,尤其是在需要向多个对象添加类似功能的情况下。
谨慎使用代理:过度使用代理可能会降低性能并增加代码复杂性。只在真正需要的时候使用代理。
测试代理:编写测试以验证代理的正确行为,包括边界条件和异常情况。

此外以下也需要重点关注:

使用设计模式来增强代理:例如,可以使用工厂模式来创建代理,或者使用单例模式来确保只有一个代理实例。
考虑使用库或框架来实现代理:有许多库和框架(如 Spring AOP)提供开箱即用的代理实现。
记录代理的用途和限制:在代码中清楚地记录为什么使用代理以及代理的限制。


5.总结

代理模式在 C++中的应用是一种有价值的工具,可以增强应用程序的控制力和效率。通过使用代理,可以实现延迟初始化、访问控制、日志记录和缓存,从而提高代码的性能和可维护性。它允许你在不改变类结构的情况下为类添加额外的功能层。在恰当应用时,代理模式可以成为你设计模式工具箱中的一个强有力武器。


http://www.ppmy.cn/embedded/37058.html

相关文章

路飞吃桃递归问题

在写代码之前&#xff0c;补充两个知识点 1.C语言递归的模版 2.递归是怎么工作的 好!话不多说让我们开始吧&#xff1a; 我们知道路飞吃了n天&#xff0c;每次都是吃一半&#xff0b;1&#xff0c;知道最后一天&#xff0c;只有一个桃子了&#xff0c;所以就可以列出式子&…

java spring cloud 企业电子招标采购系统源码:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及审…

力扣437. 路径总和 III

Problem: 437. 路径总和 III 文章目录 题目描述思路复杂度Code 题目描述 思路 1.定义int类型函数rootSum(root, targetSum)&#xff0c;用于求取每一个节点等于目标函数的路径数&#xff1a; 1.1.易知rootSum(root, targetSum)求出的数量等于rootSum(root.left, targetSum - va…

【Unity】Mathf

【Unity】Mathf 1.Math与Mathf 推荐使用Mathf Math是C#中封装好的用于数学计算的工具 类&#xff0c;Math位于System命名空间中Mathf是Unity中封装好的用于数学计算的工具 结构体&#xff0c;Mathf位于UnityEngine命名空间中Mathf比Math方法多&#xff0c;不仅包含Math中的方…

鸿蒙OpenHarmony南向:【Hi3516标准系统入门(命令行方式)】

Hi3516标准系统入门&#xff08;命令行方式&#xff09; 注意&#xff1a; 从3.2版本起&#xff0c;标准系统不再针对Hi3516DV300进行适配验证&#xff0c;建议您使用RK3568进行标准系统的设备开发。 如您仍然需要使用Hi3516DV300进行标准系统相关开发操作&#xff0c;则可能会…

分布式锁概述

什么是分布式锁 分布式锁是一种在分布式计算环境中用于同步访问共享资源的机制。它的主要目的是在一个分布式系统中&#xff0c;当多个进程或服务需要同时访问同一个资源时&#xff0c;确保任一时刻只有一个进程或服务能够执行涉及该资源的关键操作。这类似于传统单体应用中的…

基于SSM的“商店积分管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SSM的“商店积分管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统登录页面 商店首页 用户登录 用户管理 积分商品展示 摘…