博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式(11) - Proxy代理模式
阅读量:4071 次
发布时间:2019-05-25

本文共 2702 字,大约阅读时间需要 9 分钟。

目录


1.概述

  代理(Proxy)模式即给其他对象提供一种代理,并以此控制对这个对象的访问。而对一个对象进行访问控制的一个原因是,只有在我们确实需要这个对象时,才对它进行创建和初始化。它是给某一个对象提供一个替代者(占位者),使之在client对象和subject对象之间编码更有效率。代理可以提供延迟实例化(lazy initialization),控制访问等等,包括只在调用中传递。 一个处理纯本地资源的代理有时被称作虚拟代理。远程服务的代理常常称为远程代理。强制控制访问的代理称为保护代理。

  日常生活中,接触到“代理”这个概念也是挺多的。网络代理,游戏代理,代办代理等等。例如,火车票代售点即是一个代理,平时如果要买票无需去火车站,去代理点就可以了。

2.UML类图

  

3.GOF角色说明

Proxy角色

  代理角色内部包含有对真实主题的引用,从而可以在任何时候操作真实主题对象;
  代理角色提供了一个与真实主题角色相同的接口,以便可以在任何时候都能代替真实主体;
  控制真实主题的应用,负责在需要的时候创建真实主题对象(以及删除真实主题对象),即隐藏与暴露;
  代理角色通常在将客户端调用传递给真实主题之前或之后,都需要执行某个操作,而不是单纯的进行传递。

RealSubject角色

  真实主题角色定义了Proxy代理角色所代表的真实对象

Subject角色

  抽象主题角色声明了真实主题和代理主题的共同接口,这样在任何使用真实主题的地方,都可以使用代理主题。

4.代码实现

#include 
using namespace std;class Subject{public: virtual ~Subject(){}; virtual void Request() = 0;protected: Subject(){};};class RealSubject:public Subject{public: RealSubject(){}; ~RealSubject(){}; void Request() { cout<<"RealSubject Request"<
Request(); }private: Subject *_sub;};int main(){ Subject* sub = new RealSubject; Proxy* pxy=new Proxy(sub); pxy->Request(); system("pause"); return 0;}

  运行结果如下:

  Proxy Request
  RealSubject Request
  Press any key to continue . . .

5.实际场景

在需要用比较通用和复杂的对象指针代替简单的指针的时候,可以使用Proxy模式。根据使用目的来划分,可以分为下面几种:

5.1远程代理(Remote Proxy)

  为一个位于不同的地址空间的对象提供一个本地的代理对象。这个不同的地址空间可以在同一台主机中,也可以跨网络在另一台主机中,远程代理又称为大使(Ambassator)。相当于它可以隐藏一个对象存在于不同地址空间的事实,使得客户端可以访问远程机器上的对象,而远程机器可能具有更好的计算性能与处理速度,可以快速的响应并处理客户端请求,并且比客户端处理这种对象的效率高很多。因此,可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的对象是局域的而不是远程的,而代理对象承担了大部分的网络通信工作。

  本人当前所在的项目中(爱立信的某数通软件),就使用到了这种场景。FEC encoder proxy相当于是一个Remote Proxy,它负责对接收的内容参数进行编码,并向不同地址空间中的实体(UP)发送已编码的请求。

5.2虚拟代理(Virtual Proxy)

  根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。即通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗。

5.3保护代理(Protect or Access Proxy)

  控制对原始对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。因此保护代理主要用于对象应该有不同的访问权限的时候。

5.4写时复制代理(Copy-on-Write Proxy)

  它是虚拟代理的一种。把复制(克隆)操作延迟到只有在客户端真正需要时,才开始执行。拷贝一个庞大而复杂的对象是一种开销很大的操作,如果这个拷贝根本没有被修改,那么这些开销就没有必要。用代理延迟这一拷贝过程,我们可以保证只有当这个对象被修改的时候才对它进行拷贝。在实现copy-on-write时必须对实体进行引用计数。拷贝代理仅会增加引用计数。只有当用户请求一个修改该实体的操作时,代理才会真正的拷贝它。在这种情况下,代理还必须减少实体的引用计数。当引用的数目为零时,这个实体将被删除。copy-on-write可以大幅度的降低拷贝庞大实体时的开销。

5.5智能引用(Smart Reference)

  取代了简单的指针,它在访问对象时执行一些附加操作。当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。

6.代理模式的缺点

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

  另外,实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

7.对比其他相关模式

  1)适配器模式(Adapter)

  Adapater为它所适配的对象提供了一个不同的接口。相反,代理提供了与它的实体相同的接口。然而, 用于访问保护的代理可能会拒绝执行实体会执行的操作, 因此,它的接口实际上可能只是实体接口的一个子集.
  2)装饰器模式(Decorator)
  尽管Decorator的实现部分与代理相似,但Decorator的目的不一样。Decorator为对象添加一个或多个功能,而代理则控制对对象的访问。代理的实现与decorator的实现类似, 但是在相似的程度上有所差别. Protection Proxy的实现可能与decorator的实现差不多. 另一方面,Remote Proxy不包含对实体的直接引用, 而只是一个间接引用, 如"主机ID, 主机上的局部地址”. Virtual Proxy开始的时候使用一个间接引用, 例如一个文件名, 但最终将获取并使用一个直接引用.  

你可能感兴趣的文章
《软件过程管理》 第六章 软件过程的项目管理
查看>>
《软件过程管理》 第九章 软件过程的评估和改进
查看>>
《软件过程管理》 第八章 软件过程集成管理
查看>>
分治法 动态规划法 贪心法 回溯法 小结
查看>>
《软件体系结构》 练习题
查看>>
《数据库系统概论》 第一章 绪论
查看>>
《数据库系统概论》 第二章 关系数据库
查看>>
《数据库系统概论》 第三章 关系数据库标准语言SQL
查看>>
SQL语句(二)查询语句
查看>>
SQL语句(六) 自主存取控制
查看>>
《计算机网络》第五章 运输层 ——TCP和UDP 可靠传输原理 TCP流量控制 拥塞控制 连接管理
查看>>
堆排序完整版,含注释
查看>>
二叉树深度优先遍历和广度优先遍历
查看>>
生产者消费者模型,循环队列实现
查看>>
PostgreSQL代码分析,查询优化部分,process_duplicate_ors
查看>>
PostgreSQL代码分析,查询优化部分,canonicalize_qual
查看>>
PostgreSQL代码分析,查询优化部分,pull_ands()和pull_ors()
查看>>
ORACLE权限管理调研笔记
查看>>
移进规约冲突一例
查看>>
IA32时钟周期的一些内容
查看>>