设计模式(11) - Proxy代理模式

目录

1.概述

2.UML类图

3.GOF角色说明

4.代码实现

5.实际场景

5.1远程代理(Remote Proxy)

5.2虚拟代理(Virtual Proxy)

5.3保护代理(Protect or Access Proxy)

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

5.5智能引用(Smart Reference)

6.代理模式的缺点

7.对比其他相关模式


1.概述

  代理(Proxy)模式即给其他对象提供一种代理,并以此控制对这个对象的访问。而对一个对象进行访问控制的一个原因是,只有在我们确实需要这个对象时,才对它进行创建和初始化。它是给某一个对象提供一个替代者(占位者),使之在client对象和subject对象之间编码更有效率。代理可以提供延迟实例化(lazy initialization),控制访问等等,包括只在调用中传递。 一个处理纯本地资源的代理有时被称作虚拟代理。远程服务的代理常常称为远程代理。强制控制访问的代理称为保护代理。
  日常生活中,接触到“代理”这个概念也是挺多的。网络代理,游戏代理,代办代理等等。例如,火车票代售点即是一个代理,平时如果要买票无需去火车站,去代理点就可以了。

2.UML类图

  

3.GOF角色说明

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

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

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

4.代码实现

#include <iostream>
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"<<endl;
	};
};

class Proxy
{
public:
	Proxy();
	Proxy(Subject *sub)
	{
		_sub = sub;
	}
	~Proxy()
	{
		delete _sub;
	}
	void Request()
	{
		cout<<"Proxy Request"<<endl;
		_sub->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开始的时候使用一个间接引用, 例如一个文件名, 但最终将获取并使用一个直接引用.  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值