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

结构型模式之代理模式

一、概述

1、代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

2、代理对象在客户端和目标对象之间起到中介作用

3、引入一个新的代理对象,代理模式的主要目的是在不改变原始对象接口的前提下,增加额外的逻辑或控制

4、去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务

二、代理模式的结构

代理模式包含以下三个角色:

1、Subject(抽象主题角色):定义了实际对象(RealSubject)和代理对象(Proxy)共同实现的接口。这个接口定义了实际对象的行为

2、Proxy(代理主题角色):同样实现了Subject接口,但它并不直接实现功能。相反,它持有(RealSubject)的引用,并在需要时代表(RealSubject)执行操作。代理对象可以在调用(RealSubject)的方法之前或之后,添加额外的逻辑,例如权限检查等。

3、RealSubject(真实主题角色):实现了Subject接口,定义了实际的功能

三、UML图

四、代理模式实现的步骤

1、定义接口(Subject)

首先,定义一个接口类,该接口声明了代理类和目标类需要实现的公共方法。这个接口定义了代理模式的通用约定,确保客户端代码可以一致地与代理类和目标类进行交互。

class Subject
{
public:virtual ~Subject() = default;virtual void request() const = 0;
};

2、创建被代理类(RealSubject)

其次,创建被代理类(RealSubject),并实现接口中声明的方法。被代理类负责实际的功能实现,并包含客户端所需的具体业务逻辑

class RealSubject : public Subject
{
public:void request() const override{//实现具体的业务逻辑cout << "RealSubject: Handling request" << endl;}
};

3、创建代理类(ProxySubject)

然后,创建需要的代理类,代理类同样实现定义的接口。在代理类的方法中,可以添加额外的逻辑或控制。这些额外的逻辑可以在调用被代理类方法之前或之后。

class Proxy : public Subject
{
public:Proxy() : m_realSubject(std::make_shared<RealSubject>()){}void request() const override{cout << "Proxy : Logging request" << endl;m_realSubject->request();cout << "record : Logging request" << endl;}private:std::shared_ptr<RealSubject> m_realSubject;
};

4、使用代理

最后,客户端代码通过代理类与被代理类交互。客户端不需要知道代理类的存在,只需要关心接口定义的方法。代理类负责在客户端与被代理类之间传递请求,并在必要时添加额外的逻辑或控制

int main()
{std::shared_ptr<Subject> proxy = std::make_shared<Proxy>();proxy->request();return 0;
}

四、代理模式的应用场景

1、远程代理:在分布式系统中,远程代理可以代表远程对象的本地代理,从而隐藏远程访问的复杂性。它使得客户端可以像使用本地对象一样使用远程对象

2、延迟加载(懒加载):当一个对象的创建成本很高,或者它的初始化过程很复杂时,可以使用代理模式来延迟对象的创建。代理对象在真正需要时才会创建实际对象,从而提高系统的性能和效率。

3、访问控制代理模式可以控制对真实对象的访问权限。例如,可以在代理中添加权限检查,以确保只有授权用户才能访问真实对象。这在系统安全性要求较高的场景中尤为重要。

4、缓存:代理可以在内存中缓存真实对象的结果,以提高性能。例如,网络请求的代理可以缓存之前的请求结果,以避免重复的网络访问。

5、日志记录在代理对象中添加日志记录功能,记录对真实对象的访问情况。这对于调试和监控系统行为非常有用。

6、智能引用:代理模式可以提供对真实对象的智能引用,例如引用计数。当多个代理对象共享一个真实对象时,代理可以负责管理真实对象的生命周期,确保在不再需要时正确释放资源。

7、虚拟代理:当真实对象的创建开销很大或很复杂时,虚拟代理可以提供一个虚拟的对象占位符,直到真正需要对象时才会进行创建。

五、代理模式应用于远程代理

远程代理的实现中,代理模式通常会创建一个本地代理对象,该对象充当与远程对象进行交互的中介。这个本地代理对象负责处理与远程对象的通信,包括数据的序列化和反序列化、通过网络发送请求以及接收响应等。下面是一个简单的 C++ 示例,演示了如何使用代理模式来实现远程代理:

1、定义接口

首先,定义一个接口,声明远程对象和本地代理都需要实现的方法

class RemoteSubject
{
public:virtual ~RemoteSubject() = default;virtual void request() const = 0;
};

2、实现目标对象

通常,目标对象是远程服务器上实际存在的类。由于这个目标对象在本地不可直接访问,我们通常会将其实现放在服务器端。

class RealRemoteSubject : public RemoteSubject
{
public:void request() const override{cout << "RealRemoteSubject: Handling request on server" << endl;}//服务器端代码通常会包括网络通信的设备和管理,但这里为了简化示例,省略了这些部分
};

3、实现代理类

代理类在客户端与远程对象之间进行中介,处理与远程对象的通信细节

//假设我们有一个简单的网络通信库来发送请求到服务器
class NetWorkClient
{
public:void sendRequest() const{cout << "NetWorkClient: sending request to the server..." << endl;}void receiveResponse() const{cout << "NetWorkClient: Reveiving response from the server..." << endl;}
};class ProxyRemoteSubject : public RemoteSubject
{
public:ProxyRemoteSubject() : m_netWorkClient(std::make_shared<NetWorkClient>()) {}void request() const override{//代理类负责将请求转发到远程对象m_netWorkClient->sendRequest();//在实际应用中,可能需要序列化请求数据,并通过网络发送//网络操作可能会包括使用 socket、HTTP请求等cout << "ProxyRemoteSubject: Request forwarded to the server..." << endl;//接受远程服务器的响应m_netWorkClient->receiveResponse();//在实际应用中,可能需要处理响应数据//比如解析服务器返回的数据,或将响应转换为结果}
private:std::shared_ptr<NetWorkClient> m_netWorkClient;
};

4、客户端代码

客户端通过代理类与远程对象交互,代理类处理所有的网络通信细节

int main()
{std::shared_ptr< RemoteSubject> proxy = std::make_shared<ProxyRemoteSubject>();proxy->request();
}

5、总结

在远程代理模式中,ProxyRemoteSubject 类的作用是充当客户端和远程象 RealRemoteSubject 之间的中介。它不直接处理 RealRemoteSubject 的方法调用而是通过网络通信将请求转发给远程服务器上的 RealRemoteSubject

六、代理模式应用于访问控制

#include <iostream>
#include <memory>
#include <string>// 定义接口
class Subject {
public:virtual ~Subject() = default;virtual void request() const = 0;
};// 目标对象
class RealSubject : public Subject {
public:void request() const override {std::cout << "RealSubject: Handling request." << std::endl;}
};// 保护代理
class ProtectionProxy : public Subject {
private:std::shared_ptr<RealSubject> realSubject;std::string userRole;public:ProtectionProxy(const std::string& role) : realSubject(std::make_shared<RealSubject>()), userRole(role) {}void request() const override {if (userRole == "admin") {realSubject->request();} else {std::cout << "ProtectionProxy: Access denied." << std::endl;}}
};int main() {std::shared_ptr<Subject> proxy1 = std::make_shared<ProtectionProxy>("admin");proxy1->request();std::shared_ptr<Subject> proxy2 = std::make_shared<ProtectionProxy>("user");proxy2->request();return 0;
}

七、模式优点

1、能够协调调用者和被调用者,在一定程度上降低了系统的耦合度

2、客户端可以针对抽象主题角色进行编程,增加和更好代理类无须修改源代码,符合开闭原则,系统具有更好的灵活性和可扩展性

八、模式缺点

1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢(例如保护代理)

2、实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂(列如远程代理)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python习题 148:返回每个单词长度的列表
  • K8s之自动扩缩容
  • 【Python脚本】爬取网络小说
  • 谷歌、火狐及Edge等浏览器中实现allWebPlugin中间件自动安装及升级
  • docker基本环境搭建
  • 火语言RPA流程组件介绍--提取应用内嵌资源
  • java操作zookeeper
  • 【原创】java+swing+mysql健身房管理系统设计与实现
  • Adobe After Effects的插件--------CC Ball Action
  • CMake编译指令极简说明
  • Redis计数器:数字的秘密
  • vue项目关于ERR_OSSL_EVP_UNSUPPORTED的问题
  • SpringBoot集成kafka开发-消息消费的分区策略(消费者如何判断从哪个分区中消费消息的?)
  • 【C#】【EXCEL】Bumblebee/Components/Analysis/GH_Ex_Ana_CondAverage.cs
  • huggingface下载model
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • hadoop集群管理系统搭建规划说明
  • JavaScript学习总结——原型
  • Java基本数据类型之Number
  • Js基础——数据类型之Null和Undefined
  • Logstash 参考指南(目录)
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • PHP CLI应用的调试原理
  • Python 基础起步 (十) 什么叫函数?
  • React+TypeScript入门
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • 阿里研究院入选中国企业智库系统影响力榜
  • 安卓应用性能调试和优化经验分享
  • 初识 webpack
  • 翻译:Hystrix - How To Use
  • 翻译--Thinking in React
  • 高性能JavaScript阅读简记(三)
  • 前端代码风格自动化系列(二)之Commitlint
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • Python 之网络式编程
  • RDS-Mysql 物理备份恢复到本地数据库上
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • (26)4.7 字符函数和字符串函数
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (备份) esp32 GPIO
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (四)React组件、useState、组件样式
  • (图)IntelliTrace Tools 跟踪云端程序
  • (万字长文)Spring的核心知识尽揽其中
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)Neo4j下载安装以及初次使用
  • (转)Unity3DUnity3D在android下调试
  • **PHP分步表单提交思路(分页表单提交)
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .NET C# 配置 Options
  • .net core + vue 搭建前后端分离的框架