设计模式16-代理模式

设计模式16-代理模式

  • 动机
  • 定义与结构
    • 模式定义
    • 结构
  • 代码推导
  • 特点
  • 应用
  • 总结
  • 实例说明
      • 1. 远程代理
      • 2. 虚拟代理
      • 3. 保护代理
      • 4. 智能引用代理

动机

  • 在面向对象系统中有一些对象由于某种原因比如对象创建的开销很大或者某些操作需要安全控制,或者需要进程外的访问等情况。直接访问会给使用者或者系统结构带来许多麻烦。
  • 那么如何在不失去透明操作对象的同时来管理和控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。
  • 代理模式的主要动机是为某个对象提供一个代理或占位符,以便控制对该对象的访问。这种模式可以在不改变客户端代码的前提下,为对象的访问提供额外的功能,比如延迟初始化、访问控制、日志记录等。

常见的代理模式的使用场景包括:

  • 远程代理:为一个位于不同地址空间的对象提供本地代表。
  • 虚拟代理:根据需要创建开销较大的对象。
  • 保护代理:控制对原始对象的访问,可以对权限进行控制。
  • 智能引用代理:当访问对象时,执行一些附加操作,比如计数、日志记录等。

定义与结构

模式定义

为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。

结构

在这里插入图片描述
代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。在这个图例中,有几个关键组件和交互过程:

  1. Client(客户端):客户端是发起请求的一方,它不知道真正的实体对象(Subject)是如何被实现和管理的。客户端通过代理(Proxy)来间接地与实体对象交互。

  2. Subject(抽象主题/接口):这是一个定义了RealSubject和Proxy的共通接口的抽象类或接口。它声明了RealSubject和Proxy应该实现的方法,使得客户端能够通过相同的接口与它们交互。

  3. RealSubject(真实主题):这是被代理的对象,它实现了Subject接口。RealSubject包含了执行实际业务逻辑的方法。

  4. Proxy(代理):代理也是一个实现了Subject接口的对象。它持有对RealSubject的引用,并且可以控制对RealSubject的访问。代理可以在将请求传递给RealSubject之前或之后执行额外的操作,如权限检查、日志记录、事务管理等。

交互过程

  • 客户端向代理发送请求(Request())。
  • 代理接收到请求后,可能会执行一些预处理操作(如权限检查)。
  • 然后,代理将请求转发给RealSubject(如realSubject->Request(0);所示,尽管这里的表示方式略显简化)。
  • RealSubject执行实际的业务逻辑并可能返回一个结果。
  • 代理可能会接收到结果并进行后处理,然后将结果返回给客户端。

代理模式的主要优点包括:

  • 减少直接依赖:客户端与RealSubject之间的直接依赖被解耦,提高了系统的灵活性和可维护性。
  • 控制访问:代理可以决定客户端是否可以访问RealSubject,以及何时可以访问。
  • 增加额外的操作:代理可以在请求处理前后执行额外的操作,如日志记录、安全控制等。

这种模式在软件开发中非常有用,特别是当需要控制对某个对象的访问、减少系统组件之间的耦合度或者添加额外的处理逻辑时。

代理模式通常包括以下角色:

  1. Subject(抽象主题):声明了RealSubject和Proxy的公共接口,这样代理就可以用在任何使用RealSubject的地方。
  2. RealSubject(真实主题):定义了代理所代表的真实对象。
  3. Proxy(代理):保存一个引用使得代理可以访问RealSubject。实现Subject接口,代理操作在调用RealSubject之前后可以执行相关操作。

代码推导

下面是一个简单的C++代码示例,展示了代理模式的实现:

Subject接口:

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

RealSubject类:

#include <iostream>class RealSubject : public Subject {
public:void request() override {std::cout << "RealSubject: Handling request." << std::endl;}
};

Proxy类:

class Proxy : public Subject {
private:RealSubject* realSubject;public:Proxy() : realSubject(nullptr) {}~Proxy() {delete realSubject;}void request() override {if (realSubject == nullptr) {realSubject = new RealSubject();}std::cout << "Proxy: Logging the request." << std::endl;realSubject->request();}
};

客户端代码:

int main() {Proxy proxy;proxy.request(); // 实际请求通过代理进行return 0;
}

特点

优点:

  1. 控制对象访问:代理模式可以在不改变原始对象的情况下,控制对它的访问。例如,远程代理可以处理网络通信,虚拟代理可以延迟对象的创建。
  2. 增强功能:代理模式允许在不修改客户端代码的情况下增强对象的功能。例如,保护代理可以增加权限控制,智能引用代理可以记录访问日志。
  3. 解耦合:客户端与实际的实现对象解耦,客户端可以通过代理访问不同的实现对象。

缺点:

  1. 性能开销:由于增加了代理层,会造成请求处理的额外开销,尤其是在频繁调用的情况下,可能会影响性能。
  2. 复杂性增加:引入代理模式会增加系统的复杂性,增加类的数量和系统的理解难度。
  3. 潜在问题:如果不恰当地使用代理模式,可能会导致系统的设计不合理,带来维护困难。

应用

  1. 远程代理:为一个位于不同地址空间的对象提供本地代表。例如,在分布式系统中,客户端可以通过远程代理访问远程的对象。
  2. 虚拟代理:根据需要创建开销较大的对象。例如,在图形系统中,虚拟代理可以用于按需加载图像。
  3. 保护代理:控制对原始对象的访问,可以对权限进行控制。例如,在安全系统中,保护代理可以用于控制对敏感对象的访问。
  4. 智能引用代理:当访问对象时,执行一些附加操作,比如计数、日志记录等。例如,智能引用代理可以用于在访问对象时记录日志。

总结

  • 代理模式提供了一种通过代理对象控制对原始对象访问的机制,使得我们可以在不改变客户端代码的情况下,对对象的访问进行控制和增强。尽管引入代理会增加一定的性能开销和系统复杂性,但在适当的场景下使用代理模式,可以显著提高系统的灵活性和可维护性。
  • 增加一层间接层。是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中直接使用某些对象会带来很多问题作为间接层的代理对象必须解决这一问题的常见手段。
  • 具体的代理设计模式的实现方法,实现粒度,都相差很大。有些可能对单个对象的做细粒度的控制。比如拷贝。或者写技术。有些可能对组件模块提供抽象代理层在架构层次对对象做代理。
  • 代理模式并不一定要求保持接口完整的一致性。只要能够实现间接控制,有时候损失一些透明性是可以接受的。

实例说明

下面是几个不同类型的代理模式的应用场景,并通过C++代码示例来说明每种场景的实现。

1. 远程代理

远程代理用于访问位于不同地址空间的对象。在这里,我们模拟一个简单的远程方法调用。

#include <iostream>// Subject interface
class Subject {
public:virtual void request() = 0;virtual ~Subject() = default;
};// RealSubject implementation, which might be on a remote server
class RealSubject : public Subject {
public:void request() override {std::cout << "RealSubject: Handling request." << std::endl;}
};// Proxy implementation that handles communication with the remote RealSubject
class RemoteProxy : public Subject {
private:RealSubject* realSubject;public:RemoteProxy() : realSubject(nullptr) {}~RemoteProxy() {delete realSubject;}void request() override {if (realSubject == nullptr) {std::cout << "RemoteProxy: Creating RealSubject remotely." << std::endl;realSubject = new RealSubject();}std::cout << "RemoteProxy: Forwarding request to RealSubject." << std::endl;realSubject->request();}
};// Client code
int main() {RemoteProxy proxy;proxy.request(); // 实际请求通过代理进行return 0;
}

2. 虚拟代理

虚拟代理用于按需创建开销较大的对象。在这里,我们模拟一个按需加载图像的例子。

#include <iostream>// Subject interface
class Image {
public:virtual void display() = 0;virtual ~Image() = default;
};// RealSubject implementation, which represents an actual image
class RealImage : public Image {
private:std::string filename;void loadFromDisk() {std::cout << "Loading " << filename << std::endl;}public:RealImage(const std::string& filename) : filename(filename) {loadFromDisk();}void display() override {std::cout << "Displaying " << filename << std::endl;}
};// Proxy implementation that creates RealImage only when needed
class ProxyImage : public Image {
private:std::string filename;RealImage* realImage;public:ProxyImage(const std::string& filename) : filename(filename), realImage(nullptr) {}~ProxyImage() {delete realImage;}void display() override {if (realImage == nullptr) {realImage = new RealImage(filename);}realImage->display();}
};// Client code
int main() {ProxyImage image("test.jpg");image.display(); // Loading and displaying the imageimage.display(); // Displaying the already loaded imagereturn 0;
}

3. 保护代理

保护代理用于控制对原始对象的访问,可以对权限进行控制。这里我们模拟一个简单的权限控制例子。

#include <iostream>// Subject interface
class Subject {
public:virtual void request() = 0;virtual ~Subject() = default;
};// RealSubject implementation, which represents an actual service
class RealSubject : public Subject {
public:void request() override {std::cout << "RealSubject: Handling request." << std::endl;}
};// Proxy implementation that controls access to RealSubject
class ProtectionProxy : public Subject {
private:RealSubject* realSubject;bool accessGranted;public:ProtectionProxy(bool access) : realSubject(new RealSubject()), accessGranted(access) {}~ProtectionProxy() {delete realSubject;}void request() override {if (accessGranted) {std::cout << "ProtectionProxy: Access granted." << std::endl;realSubject->request();} else {std::cout << "ProtectionProxy: Access denied." << std::endl;}}
};// Client code
int main() {ProtectionProxy proxyWithAccess(true);proxyWithAccess.request(); // Access granted, forwarding request to RealSubjectProtectionProxy proxyWithoutAccess(false);proxyWithoutAccess.request(); // Access denied, not forwarding requestreturn 0;
}

4. 智能引用代理

智能引用代理在访问对象时执行一些附加操作,如引用计数、日志记录等。这里我们模拟一个记录访问日志的例子。

#include <iostream>
#include <memory>// Subject interface
class Subject {
public:virtual void request() = 0;virtual ~Subject() = default;
};// RealSubject implementation, which represents an actual service
class RealSubject : public Subject {
public:void request() override {std::cout << "RealSubject: Handling request." << std::endl;}
};// Proxy implementation that logs access to RealSubject
class LoggingProxy : public Subject {
private:std::shared_ptr<RealSubject> realSubject;public:LoggingProxy() : realSubject(std::make_shared<RealSubject>()) {}void request() override {std::cout << "LoggingProxy: Logging request." << std::endl;realSubject->request();}
};// Client code
int main() {LoggingProxy proxy;proxy.request(); // Logging the request and forwarding it to RealSubjectreturn 0;
}

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

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

相关文章

【嵌入式之RTOS】死锁问题详解

目录 一、什么是死锁 二、产生死锁的四个必要条件 三、避免死锁的方法 四、实际应用中的考虑 一、什么是死锁 死锁&#xff08;Deadlock&#xff09;是多任务或多线程环境中一个常见的问题&#xff0c;尤其是在实时操作系统&#xff08;RTOS&#xff09;中&#xff0c;如果…

SpringBoot(看这一篇就够了)

目录&#xff1a; SpringBootSpring的缺点什么是SpringBoot&#xff1f;Springboot3 版本要求Springboot的三种构建方式官网搭建通过IDEA脚手架搭建通过Maven搭建项目 SpringBoot的项目结构编写一个测试代码YAML文件自定义配置文件Value读取配置文件ConfigurationProperties读取…

汽车空调歧管压力表的使用

(1)在手动低压阀开启、手动高压阀关闭状态下&#xff0c;低压管路、中间管路与低压表相通开此时可进行从低压侧加注制冷剂或排放制冷剂&#xff0c;并可同时检测高、低侧的压力。 (2)在手动低压阀关闭、手动高压阀开启状态下&#xff0c;高压管路、中间管路与高压表相通&#x…

【网络请求调试神器,curl -vvv 返回都有什么】

curl -vvv 是一个用于在命令行中执行 HTTP 请求的命令&#xff0c;其中 -vvv 是一个选项&#xff0c;用于启用详细的调试输出。 vvv: 这是一个选项&#xff0c;表示启用详细的调试输出。每个 v 增加调试信息的详细程度&#xff0c;vvv 是最高级别的详细输出。 详细输出包括&a…

PDF转Word神器!这四款既免费又好用~

作为当代合格的打工人之一&#xff0c;人手必备的办公技能之一难免就是各种文档的处理&#xff0c;包括了编辑、格式转换等等的基本需要掌握的技能了&#xff0c;其中的pdf转word就可以实现在线免费转换&#xff0c;今天特地通过这篇文章整理了四款免费在线转换的工具&#xff…

七言-绝美崇州

题记 今天&#xff0c;2024年07月30日&#xff0c;在看到《今日崇州》 发布的航拍风光照片之后&#xff0c;这才方知笔者虽已寄居崇州“西川第一天”街子古镇养老逾五年&#xff0c;竟然不知崇州拥有如此之多的青山绿水&#xff0c;集生态、宜居、智慧、文化、旅游丰富资源于一…

学习记录——day22 文件IO

文件IO是使用系统调用&#xff08;内核提供的函数&#xff09;来完成数据的读写操作&#xff0c;不提供缓冲区&#xff0c;基于文件描述符操作文件&#xff0c;每进行一次文件io操作&#xff0c;进程就会从用户空间向内核空间进行一次切换&#xff0c;效率没有标准io高。 文件…

Kubernetes 学习记录

https://note.youdao.com/ynoteshare/index.html?idbc7bee305611b52d6900ba209a92bd4d&typenote&_time1694072007342 概览 K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ K8S 是Kubernetes的全称&#xff0c;源于希腊语&#xff0c;意为“舵手”或“…

接口自动化中对于文件上传的处理方法

正常的接口自动化基本都是json的格式&#xff0c;对于文件上传是一种特殊的格式是表单格式针对这种表单格式在接口自动化中怎么处理&#xff0c;主要通过工作中使用的一个实际的例子进行分享 举例&#xff1a;web上需要导入一个文件实现相关的功能&#xff0c;主要通过两个接口…

oracle表、表空间使用空间

文章目录 一、Oracle查询表空间占用情况二、Oracle查询表占用的空间三、Oracle查询表空间使用情况四、Oracle查询每张表占用空间五、表空间大小 TOC 一、Oracle查询表空间占用情况 oracle日常工作中查看表占用空间大小是数据库管理中的基本操作&#xff1a; SELECT a.tablesp…

nginx续1:

八、虚拟主机配置 基于域名的虚拟主机 [rootserver2 ~]# ps -au|grep nginx //查看进程 修改Nginx服务配置&#xff0c;添加相关虚拟主机配置如下 1. [rootproxy ~]# vim /usr/local/nginx/conf/nginx.conf 2. .. .. 3. server { 4. listen …

【SuperMap iServer 服务列表未授权访问漏洞】怎么处理

今天遇到这样一个安全问题需要处理&#xff1a; 漏洞名称&#xff1a; 接口未授权访问。 漏洞URL&#xff1a; https://****/iserver/services 漏洞描述&#xff1a; 多个服务存在未授权访问&#xff0c;可访问清除缓存等功能。 查阅官方社区发现有两个解决办法&#xff1…

在 Vim 编辑器中,如果某个单词被意外地高亮显示,使用:noh可以取消高亮显示

文章目录 1、问题出现的背景2、解决办法 1、问题出现的背景 配置镜像加速器&#xff0c;修改 /etc/docker/daemon.json 目录下的文件&#xff0c;不小心高亮显示https&#xff0c;产生问题的步骤是&#xff0c;我先是按esc键退出vim的编辑模式&#xff0c;然后在https的前面按…

《计算机应用文摘》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《计算机应用文摘》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是维普收录的正规学术期刊。 问&#xff1a;《计算机应用文摘》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;重庆西南信息有限公司 主办单位&#x…

需求跟踪矩阵:项目管理的“指南针”

前言 在项目的茫茫大海中&#xff0c;需求如同潮汐般汹涌澎湃&#xff0c;而我们则是那驾船的舵手&#xff0c;需要在波涛汹涌中找到正确的航向。如何确保每一个需求都能得到满足&#xff0c;同时又不偏离项目的主线&#xff1f;这就需要我们借助一种强大的工具——需求跟踪矩…

springboot超市商品管理系统-计算机毕业设计源码55289

摘 要 随着信息技术的快速发展和普及&#xff0c;传统的超市管理模式已经无法满足现代商业的需求。为了提高超市的管理效率&#xff0c;优化商品销售流程&#xff0c;本文提出了一种基于SpringBoot框架的超市商品管理系统。该系统结合了现代软件开发技术&#xff0c;包括MySQL数…

【策略工厂模式】记录策略工厂模式简单实现

策略工厂模式 1. 需求背景2. 代码实现2.1 定义基类接口2.2 排序策略接口定义2.3 定义抽象类&#xff0c;实现策略接口2.4 具体的排序策略实现类2.5 实现策略工厂类2.6 控制类 3. 启动测试4. 总结 1. 需求背景 现在需要你创建一个策略工厂类&#xff0c;来根据策略实现各种排序…

第三周:网络应用(上)

一、网络应用&#xff08;层&#xff09;内容概述 我们已经知道&#xff0c;Internet的体系结构是符合TCP/IP协议栈的&#xff0c;而“应用层”就在这个协议的最上层。 本讲内容包括&#xff1a; 二、网络应用的基本原理 常见网络应用包括&#xff1a; 问&#xff1a;网络应…

【机器学习】正规方程的简单介绍以及如何使用Scikit-Learn实现基于正规方程的闭式解线性回归

引言 Scikit-learn 是一个开源的机器学习库&#xff0c;它支持 Python 编程语言。它提供了多种机器学习算法的实现&#xff0c;并用于数据挖掘和数据分析 文章目录 引言一、正规方程的定义二、正规方程的原理三、使用 Scikit-Learn 实现基于正规方程的闭式解线性回归3.1 工具3.…

如何使用rdma-core来实现RDMA操作

rdma-core 是一个开源项目&#xff0c;为远程直接内存访问&#xff08;RDMA&#xff09;提供用户空间的支持。它包括 RDMA 设备的驱动程序、库和工具&#xff0c;旨在简化 RDMA 应用的开发和部署。 基础知识参考博文&#xff1a; 一文带你了解什么是RDMA RDMA 高性能架构基本…