C++设计模式——Proxy代理模式

一,代理模式简介

代理模式是一种 结构型设计模式,该模式通过引入一个新的代理对象Proxy,来间接访问原始对象,从而使访问方式变得灵活和可控。
代理对象的设定减少了客户端与真实对象之间的直接交互。
通过引入代理对象来间接访问原始的对象,达到延迟访问和隔离的效果,这就是代理模式的主要用途。
举个例子:
当有多个客户端对数据库发起大批量请求时,数据库由于需要同时处理多个请求,导致其处理速度变得很慢。
此时如果有一个代理,用法上和数据库一致,这个代理先收集来自多个客户端的请求,进行缓存,然后逐渐转发给数据库,避免了通道发生阻塞,那么数据库此时的处理速度会大大提升。

二,代理模式的结构

1.抽象对象(Subject):定义了真实对象和代理对象的共同接口。

2.真实对象(RealSubject):又称为被代理对象,代理模式中的核心角色,定义了真正需要被代理的业务逻辑。

3.代理对象(Proxy):充当了客户端与真实对象之间的中介。

对应UML类图:

1.Subject定义了Proxy和RealSubject的公共接口。

2.Proxy和RealSubject都实现了Subject的接口。

3.客户端(Client)通过Proxy与RealSubject进行交互。

4.RealSubject负责完成主要的接口实现,Proxy负责控制外部Client对接口的访问。

5.Proxy内部包含对Subject的对象指针或引用,因此Proxy可以进一步调用子类RealSubject中的函数(forward calls)。

6.在某些情况下,Proxy可以用来完成RealSubject实例的创建与销毁。

7.Client是使用Proxy的对象,它通过Proxy来访问和操作RealSubject。

代码实现:

#include <iostream>
using namespace std;class Subject
{
public:virtual void request() = 0;virtual ~Subject() {}
};class RealSubject : public Subject
{
public:void request() {cout << "RealSubject.request()" << endl;}
};class Proxy : public Subject
{
private:Subject* realSubject;
public:Proxy(){realSubject = new RealSubject();}~Proxy(){delete realSubject;}// Forward calls to the RealSubject:void request() {realSubject->request();}
};int main() {Proxy p;p.request();
}

运行结果:

RealSubject.request()

补充:在C++编码中,确实可以通过继承和虚函数实现父类调用子类的成员函数,这是C++多态特性的一种常见应用方式。

#include <iostream>
using namespace std;class Base {
public:virtual void print() { cout << "Base class method" << endl; }
};class Derived : public Base {
public:// 重写父类的虚函数virtual void print() override { cout << "Derived class method" << endl;  }
};int main() {// 父类对象调用子类方法Base* baseObj = new Derived();baseObj->print();
}

运行结果:

Derived class method

三,代理模式的种类

简单代理(Simple Proxy):主要用于转发请求和处理一些基本操作,例如添加日志、计时等。

远程代理(Remote Proxy):当主体对象在另一个地址空间(如网络地址)时,远程代理会提供远程通信的功能,进行数据的访问和转换。

智能引用代理(Smart Reference Proxy):也称为共享代理,它维护了多个客户端对同一目标的共享引用,并提供统一的接口。

虚拟代理(Virtual Proxy):延迟针对昂贵资源的访问,只有在真正使用时才加载。

保护代理(Protection Proxy):主要用于访问权限的控制,比如身份验证、授权等。

四,代理模式的应用场景

1.延迟加载:使资源密集型的对象仅仅在被使用时才加载,例如,访问大型数据库、加载大批量图像数据等。

2.访问控制:代理可以通过添加身份验证来控制对真实主体的访问,可用于保护敏感数据。

3.缓存机制:代理可以缓存高频次的请求,从而减少系统开销,优化性能。

4.日志记录和监控:代理可用于记录或监控对真实主体执行的操作,而无需修改其代码。

5.远程访问:在分布式系统中,真实主体可能位于不同的计算机上,代理模式可以隐藏远程通信的复杂细节。

6.状态管理:代理可以同步管理多个客户端所共享的真实主体的状态,确保它们的一致性。

五,代理模式的优缺点

代理模式的优点:

可以在不修改被代理对象的情况下,增加额外的功能或控制访问方式。

可以在访问对象之前和之后进行一些处理,比如添加日志、添加时间戳等。

可以实现远程代理,使得客户端可以通过网络访问远程的对象。

可以防止未经授权访问真实主体。

代理模式的缺点:

引入新的类,增加代码复杂性。

读取资源时,需要通过代理来间接访问,造成额外的性能损失。

六,代码实战

开发场景:基于Proxy模式来模拟对图片的延迟加载和显示控制。

1.创建Subject

//Step 1: Define the Subject interface
class Image {
public:virtual void display() = 0;
};

2.创建RealSubject

//Step 2: Implement the Real Object
class RealImage : public Image {
private:std::string filename;
public:RealImage(const std::string& filename) : filename(filename) {// Simulate loading the imagestd::cout << "Loading image: " << filename << std::endl;}void display() override {std::cout << "Displaying image: " << filename << std::endl;}
};

3.Proxy类实现与RealSubject相同的接口,并维护对RealSubject的引用。

//Step 3: Create the Proxy
class ImageProxy : public Image {
private:// Reference to the Real ObjectRealImage* realImage;std::string filename;public:ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}void display() override {if (realImage == nullptr) {realImage = new RealImage(filename);}realImage->display();}
};

完整代码实现:

#include <iostream>
#include <bits/stdc++.h>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) {// Simulate loading the imagestd::cout << "Loading image: " << filename << std::endl;}void display() override {std::cout << "Displaying image: " << filename << std::endl;}
};class ImageProxy : public Image {
private:// Reference to the Real ObjectRealImage* realImage; std::string filename;public:ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}void display() override {if (realImage == nullptr) {realImage = new RealImage(filename);}realImage->display();}
};int main() {//Create a proxy to an imageImage* image = new ImageProxy("example.jpg");//Display the imageimage->display();//Displaying the image againimage->display();delete image;return 0;
}

运行结果:

Loading image: example.jpg
Displaying image: example.jpg
Displaying image: example.jpg

七,参考阅读

https://www.geeksforgeeks.org/proxy-pattern-c-design-patterns/

https://www.bogotobogo.com/DesignPatterns/proxy.php

https://design-patterns.readthedocs.io/zh-cn/latest/structural_patterns/proxy.html

https://refactoring.guru/design-patterns/proxy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1450878.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

VRChat 2024年裁员原因与背景深度分析

VRChat&#xff0c;作为2022年元宇宙/VR社交领域的巨头&#xff0c;近期在2024年宣布裁员计划&#xff0c;其背后原因和背景值得业界尤其是仍在纯元宇宙虚拟空间创业的同仁们重点关注。 一、创始人决策失误 根据CEO的邮件披露&#xff0c;VRChat的创始人因缺乏经验和过度自信…

网络安全 - kali 安装

文章目录 Kali 安装教程下载镜像 Kali 安装教程 下载镜像 kali-images安装包下载_开源镜像站-阿里云 (aliyun.com) 下载对应镜像&#xff08;自己挑&#xff09; 打开本机 cmd 并输入一下命令 ipconfig找到 NAT 模式的 IP 地址并从虚拟机中 ping

【Linux】环境设置MySQL表名忽略大小写

目录 说明 一、摘要 二、查看服务器上MySQL情况 方式一&#xff1a;通过Linux方式 方式二&#xff1a;借助可视化工具&#xff08;Navicat&#xff09; 三、MySQL设置忽略表名大小写的参数&#xff08;lower_case_table_names&#xff09; 四、网上解决方案 方法一&…

基于线性核函数的SVM数据分类算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于线性核函数的SVM数据分类算法matlab仿真&#xff0c;通过程序产生随机的二维数据&#xff0c;然后通过SVM对数据进行分类&#xff0c;SVM通过编程实现&#x…

94. 二叉树的中序遍历 (Swift版本, 递归)

题目描述 使用递归方法解题 使用了一个递归函数 inorder 来进行二叉树的中序遍历&#xff0c;并将结果存储在数组 ret 中 /*** Definition for a binary tree node.* public class TreeNode {* public var val: Int* public var left: TreeNode?* public var ri…

Python | Leetcode Python题解之第149题直线上最多的点数

题目&#xff1a; 题解&#xff1a; class Solution:def maxPoints(self, points: List[List[int]]) -> int:n len(points)if n < 2:return nres 2for i in range(n):x1, y1 points[i][0], points[i][1]has {}for j in range(i 1, n):x2, y2 points[j][0], points…

x64汇编fastcall调用约定

x64汇编环境&#xff1a;只需要在x86基础上对项目属性进行设置&#xff0c;将平台设置为所有平台&#xff1b; 以及在将debug改为x64模式即可&#xff1a; 后续写完代码直接生成项目再使用本地调试器进行运行即可。 fastcall调用约定 在x64架构下&#xff0c;fastcall调用约定…

【StableDiffusion】采样方法对比优缺点及评估,采样器 调度器(目前已有的 采样器介绍与评估)

采样器 Sampler 采样方法 决定了 如何从 噪声 生成 图像 的过程&#xff0c;也就是去噪过程如何进行 包含 DPM 的采样方法&#xff08;逆转扩散采样&#xff09; DPM → Diffusion Probabilistic Models&#xff08;扩散概率模型&#xff09; DPM、DPM2 包含 DPM 的采样方…

解决CentOS的yum命令失效的问题

近日笔者对一台装有 CentOS 7.9 系统的服务器反复折腾&#xff0c;玩到最后发现 yum 命令用不了&#xff0c;总是报下面的错误信息&#xff1a; There was a problem importing one of the Python modules required to run yum. The error leading to this problem was:/usr/l…

C# WPF入门学习主线篇(二十八)—— 使用集合(ObservableCollection)

C# WPF入门学习主线篇&#xff08;二十八&#xff09;—— 使用集合&#xff08;ObservableCollection&#xff09; 在WPF中&#xff0c;数据绑定是构建动态和响应式用户界面的关键。ObservableCollection是一个特别有用的集合类型&#xff0c;它不仅支持数据绑定&#xff0c;还…

Python | Leetcode Python题解之第150题逆波兰表达式求值

题目&#xff1a; 题解&#xff1a; class Solution:def evalRPN(self, tokens: List[str]) -> int:op_to_binary_fn {"": add,"-": sub,"*": mul,"/": lambda x, y: int(x / y), # 需要注意 python 中负数除法的表现与题目不一…

面试题记录1

题目&#xff1a; 给定一个输入序列01101001101101101找出序列为1101并统计其个数。请用有限状态机&#xff08;FSM&#xff09;实现。 解题&#xff1a; 代码&#xff1a; module sequence_detector(input wire clk, // 时钟信号input wire reset, // 复位信号input wir…

JasperReport-报表中文不显示问题解决

在用Jaspersoft Studio进行报表设计的时候默认采用的字体是SansSerif&#xff0c;通过jasperreport的JAVA SDK进行报表输出时就会出现中文不显示问题。另外即便在Jaspersoft Studio设置的是中文字体&#xff0c;通过JAVA端生成也可能出现中文不显示。原因是SDK包中没有包含中文…

Github 2024-06-13开源项目日报Top10

根据Github Trendings的统计,今日(2024-06-13统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目3非开发语言项目2Shell项目1TypeScript项目1Swift项目1PHP项目1Blade项目1JavaScript项目1从零开始构建你喜爱的技术 创建周期:2156…

【单片机毕业设计选题24003】-基于STM32和阿里云的家庭安全监测系统

系统功能: 此设计采用STM32单片机采集环境温湿度,烟雾浓度和一氧化碳浓度显示在OLED上&#xff0c;并将这些信息上报至阿里云平台。 1. 上电连接手机热点后自动连接阿里云&#xff0c;可通过阿里云平台收到系统上报的温湿度&#xff0c;烟雾 浓度&#xff0c;一氧化碳数据以…

日常销售数据分析为什么重要?三个维度全面分析日常销售数据

在当今电子商务的浪潮席卷全球的时代&#xff0c;网店如雨后春笋般涌现&#xff0c;并且竞争日趋激烈。在这样一个充满挑战与机遇的环境中&#xff0c;如何洞察市场动向&#xff0c;把握消费者需求&#xff0c;实现销售业绩的稳步增长&#xff0c;成为每一位电商运营者必须面对…

Jenkins For Windows编译构建C#项目环境搭建(完整版)

安装Jenkins 下载Windows安装包 官方下载地址 选择稳定版&#xff0c;这里下载的是最新版&#xff0c;如需下载指定版本点击 以前的发行版 配置java环境 下载 java jdk 17 jdk17官方下载链接 这里下载的是msi版本的安装包 安装jdk17 双击运行安装包&#xff0c;一直下…

Java | Leetcode Java题解之第150题逆波兰表达式求值

题目&#xff1a; 题解&#xff1a; class Solution {public int evalRPN(String[] tokens) {int n tokens.length;int[] stack new int[(n 1) / 2];int index -1;for (int i 0; i < n; i) {String token tokens[i];switch (token) {case "":index--;stack…

【分布式技术专题】「OceanBase深度解析」 探索OceanBase产品矩阵与核心设计

探索OceanBase产品矩阵与核心设计 OceanBase的六大特性高扩展高可用多租户&#xff08;资源隔离&#xff09;OceanBase架构和功能OceanBase广泛的数据源支持 OceanBase的六大特性 OceanBase以其卓越的产品平台整合方案&#xff0c;充分展现了六大核心特性的卓越与全面。这一方…

PID算法的离散化和参数调节方式的介绍

目录 概述 1 背景介绍 2 数字式 PID 控制算法 2.1 位置式 PID 2.2 增量式 PID 2.3 两种算法比较 3 控制器参数整定 3.1 凑试法 3.2 临界比例法 3.3 经验法 4 参数调整规则的探索 概述 本文主要介绍离散化PID算法的实现原理&#xff0c;以方便对其进行数字化的处理&a…