意图
为其他对象提供一种代理以控制对这个对象的访问
动机
对一个对象进行访问控制的原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化
典型例子:智能指针的实现,通过引用计数来决定“=” 复制构造函数,析构的实现,参见Smart Pointer 智能指针
结构
Proxy
保存一个引用使得代理可以访问实体。若RealSubject和Subject的接口相同,Proxy会引用Subject,就相当于在代理类中保存一个Subject指针,该指针会指向RealSubject;
提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体;
控制对实体的存取,并可能负责创建和删除它;
其它功能依赖于代理的类型,例如:
远程代理负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求;
虚代理可以缓存实体的附加信息,以便延迟对它的访问;
保护代理检查调用者是否具有实现一个请求所必须的访问权限。
Subject:定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy;
RealSubject:定义Proxy所代理的实体。
实现
1 #include <iostream> 2 using namespace std; 3 4 #define SAFE_DELETE(p) if (p) { delete p; p = NULL;} 5 6 class CSubject 7 { 8 public: 9 CSubject(){}; 10 virtual ~CSubject(){} 11 12 virtual void Request() = 0; 13 }; 14 15 class CRealSubject : public CSubject 16 { 17 public: 18 CRealSubject(){} 19 ~CRealSubject(){} 20 21 void Request() 22 { 23 cout<<"CRealSubject Request"<<endl; 24 } 25 }; 26 27 class CProxy : public CSubject 28 { 29 public: 30 CProxy() : m_pRealSubject(NULL){} 31 ~CProxy() 32 { 33 SAFE_DELETE(m_pRealSubject); 34 } 35 36 void Request() 37 { 38 if (NULL == m_pRealSubject) 39 { 40 m_pRealSubject = new CRealSubject(); 41 } 42 cout<<"CProxy Request"<<endl; 43 m_pRealSubject->Request(); 44 } 45 46 private: 47 CRealSubject *m_pRealSubject; 48 }; 49 50 int main() 51 { 52 CSubject *pSubject = new CProxy(); 53 pSubject->Request(); 54 SAFE_DELETE(pSubject); 55 }
区分代理,适配器和装饰
适配器Adapter为它所适配的对象提供了一个不同的接口。相反,代理提供了与它的实体相同的接口。然而,用于访问保护的代理可能会拒绝执行实体会执行的操作,因此,它的接口实际上可能只是实体接口的一个子集。
尽管Decorator的实现部分与代理相似,但Decorator的目的不一样。Decorator为对象添加一个或多个功能,而代理则控制对对象的访问。