【设计模式学习笔记十三】【结构型模式】【代理模式(Proxy)】

来源:互联网 发布:图书销售数据分析 编辑:程序博客网 时间:2024/06/16 11:01

本文是学习刘伟技术博客和《设计模式-可复用面向对象软件的基础》笔记,博客链接:http://blog.csdn.net/lovelion/article/details/17517213

主要是对博客和书本做提炼和记录,更多是对设计模式的基础框架学习,细节将略去,侧重对每个设计模式框架的理解。

我应该理解和掌握的:

1)能够画出这个设计模式的架构框图;

2)能够根据架构框图写出对应的伪代码;

3)这个模式的应用场景,主要优缺点。

1.代理模式

在软件开发中,有一种模式类似于代购,即客户端由于某种原因不想或不能直接访问一个对象,此时可以通过一个代理对象来实现间接访问,该方案被称为代理模式。

(1)定义

代理模式:为其他对象提供一种代理以控制对这个对象的访问。

代理又可分为四种:

a)远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是同一台主机中,也可以在另一台主机中,远程代理又称为大使。

b)虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正的创建。

c)保护代理(Protect Proxy):控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。

d)缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。

e)智能引用代理(Smart Reference Proxy):当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来,比如智能指针。

1)代理模式结构图


2)参与者

a) Subject(抽象主题角色):定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用proxy。

b) RealSubject(真实主题角色):定义了Proxy所代表的实体。

c) Proxy(代理):保存一个引用是的代理可以访问实体;提供一个与Subject相同的接口,这样代理就可以用来替代实体;控制对实体的存取,并可能负责创建或删除它;其他功能依赖于代理的类型。

3)看图写代码

/*** FileName     : ProxyPattern** Author       : lin005** Date         : 2015/01/29** Description  : More information, please go to http://blog.csdn.net/amd123456789*/#include<iostream>#include<windows.h>using namespace std;//抽象主题角色class Subject{public:virtual void Request() = 0;};//真实主题角色class RealSubject:public Subject{public:void Request(){cout<<"RealSubject Request()"<<endl;}};//代理class Proxy:public Subject{public:Proxy(){real = new RealSubject();}~Proxy(){if(real != NULL){delete real;real = NULL;}}void preRequest(){cout<<"preRequest()"<<endl;}void postRequest(){cout<<"postRequest"<<endl;}//调用真正实体void Request(){preRequest();real->Request();postRequest();}private:RealSubject *real;};//客户端测试类int main(){Subject *proxy = new Proxy();proxy->Request();if(proxy){delete proxy;proxy = NULL;}return 0;}

4)智能指针

智能指针,使用引用计数时,也可以看做是代理模式的应用。下面例子中,SmartPtr就是代理类,实际对象是ptr;SmartPtr代理ptr的行为,运用引用计数,实现智能指针。

代码来自百度百科:

/*** FileName     : ProxyPattern** Author       : lin005** Date         : 2015/01/30** Description  : More information, please go to http://blog.csdn.net/amd123456789*///被代理的对象class Stub{public:void print(){cout<<"test"<<endl;}~Stub(){cout<<"stub::destructor"<<endl;}};//可以看做代理template<typename T>class SmartPtr{public:SmartPtr(T* p = 0):ptr(p),count(new size_t(1)){}SmartPtr(const SmartPtr<T> & src):ptr(src.ptr),count(src.count){++*count;}//重载赋值操作符SmartPtr& operator=(const SmartPtr & src){++*src.count;release();ptr = src.ptr;count = src.count;return *this;}T* operator->(){if(ptr)return ptr;}const T* operator->()const{if(ptr)return ptr;}T& operator*(){if(ptr)return *ptr;}const T& operator*()const{if(ptr)return *ptr;}~SmartPtr(){release();}private:void release(){if(--*count == 0){delete ptr;delete count;}}private:T* ptr;//真实对象size_t* count;//引用计数};int main(){//智能指针,类型为StubSmartPtr<Stub> t;t->print();//print testSmartPtr<Stub> t1(new Stub());SmartPtr<Stub> t2(t1);SmartPtr<Stub> t3(new Stub());t3= t2;//call t3 destructort1->print(); //print(*t3).print(); //printreturn 0;/*输出结果:teststub::destructor (析构t3)testteststub::destructor (析构t1)请按任意键继续. . .*/}

(2)总结

1)优点

a) 能够协调调用者和被调用者,在一定程度上降低了系统的耦合。

b) 客户端可以针对抽象角色进行编程。

2)缺点

a) 增加代理对象有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。

b) 是在代理模式需要额外的工作,并且有些代理模式实现过程较为复杂,例如远程代理。

(3)适用场景

1)远程代理为一个对象在不同的地址空间提供局部代表;

2)虚代理根据需要创建开销很大的对象。

3)当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时使用保护代理

4)当需要为一个对象的访问提供额外的操作时,可以使用智能引用代理。

0 0