c++设计模式之一:代理模式

什么是代理模式?

在GOF的《设计模式:可复用面向对象软件的基础》一书中对代理模式是这样说的:为其他对象提供一种代理以控制对这个对象的访问。结合上面的游戏代理的例子和下面的图,我们来进行分析一下。以前你是这样玩游戏:

现在有了游戏代理,你是这样玩游戏:

代理服务器干了什么?它代替你去和游戏服务器进行交互。它访问游戏服务器的速度比你使用校园网访问游戏服务器的速度快很多。所以,你的游戏延迟就下来了。

代理模式分为四类:远程代理,虚代理,保护代理和智能引用。在下面使用场合会对这四种进行分别介绍。

UML类图

Proxy

  1. 保存一个引用使得代理可以访问实体。若RealSubject和Subject的接口相同,Proxy会引用Subject,就相当于在代理类中保存一个Subject指针,该指针会指向RealSubject;
  2. 提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体;
  3. 控制对实体的存取,并可能负责创建和删除它;
  4. 其它功能依赖于代理的类型,例如:
    远程代理负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求;
    虚代理可以缓存实体的附加信息,以便延迟对它的访问;
    保护代理检查调用者是否具有实现一个请求所必须的访问权限。

Subject:定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy;

RealSubject:定义Proxy所代理的实体。

使用场合

上面也总结了,代理模式分为远程代理,虚代理,保护代理和智能引用这四种,而分为这四种,就是对应不同的使用场合的。

    1. 远程代理为一个对象在不同的地址空间提供局部代理;
    2. 虚代理根据需求创建开销很大的对象;
    3. 保护代理控制原始对象的访问;保护代理用于对象应该有不同的访问权限的时候;
    4. 智能引用取代了简单的指针,它在访问对象时执行一些附加操作,它的典型用途包括:
      对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它;
      当第一次引用一个持久对象时,将它装入内存;
      在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

代码实现

最简单的实现,对上述UML类图的直接代码体现:

#include<iostream>
using namespace std;

#define SAFE_DELETE(p) if(p){delete p; p=NULL;}

//接口
class CSubject
{
public:
	CSubject() {};
	virtual ~CSubject(){}
	virtual void Request() = 0;
};


//实际要访问的类,代理类要操纵的实体
class CRealSubject :public CSubject
{
public:
	CRealSubject() {}
	~CRealSubject() {}

	void Request()
	{
		cout << "CRealSubject Request" << endl;
	}
};

//代理类,其就是控制对实际访问对象的访问,与适配器模式的区别在于适配器模式中两个对象分别是实现了不同的接口
//而代理类是实现的同一个接口
//与装饰器模式的区别在与,装饰器模式是在共有的核心功能的基础上加上了一些特有的功能,每个装饰器添加的功能不一样
class CProxy :public CSubject
{
public:
	CProxy() :m_pRealSubject(NULL) {}
	~CProxy(){SAFE_DELETE(m_pRealSubject);}

	void Request()
	{
		if (m_pRealSubject == NULL)
		{
			m_pRealSubject = new CRealSubject();
		}
		cout << "CProxy Request"<<endl;
		m_pRealSubject->Request();
	}
private:
	CRealSubject* m_pRealSubject;
};


int main(int argc, char* argv[])
{
	CSubject* pSubject = new CProxy();
	pSubject->Request();
	SAFE_DELETE(pSubject);
}

总结

我在第一次接触代理模式的时候,看它的UML类图,发现它和适配器模式的类适配器很像,再一看,又和装饰模式非常像;不仔细区分,真的是很容易混乱的。下面就做简单的区分,说多了也都是“狡辩”了。

  1. 适配器Adapter为它所适配的对象提供了一个不同的接口。相反,代理提供了与它的实体相同的接口。然而,用于访问保护的代理可能会拒绝执行实体会执行的操作,因此,它的接口实际上可能只是实体接口的一个子集。
  2. 尽管Decorator的实现部分与代理相似,但Decorator的目的不一样。Decorator为对象添加一个或多个功能,而代理则控制对对象的访问。

我在这里进行区分,你们看了,也就像我在咬文嚼字一样;这就是结构型设计模式;它们之间都有一些细微的差别。你也可以说,在适配器模式进行接口适配时,添加一些数据转换就变成了远程代理;你也可以说装饰模式虽然功能不一样,在我看来,大同小异;是的,不管你怎么说,就像1000个读者心中有1000个哈姆雷特一样,每个人对设计模式的理解都是不一样的;最重要的是我们能在实际应用中进行活学活用,如果能做到这个;不管什么设计模式,那只是一个名字,就像对于富人来说,钱只是一个银行卡上的一个数字一样。

发布了199 篇原创文章 · 获赞 77 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/tianguiyuyu/article/details/103899357