代理模式
代理模式定义:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
图15-2 代理模式结构图
(3) RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。
典型的抽象主题类代码如下:
abstract class Subject { public abstract void Request(); }
真实主题类继承了抽象主题类,提供了业务方法的具体实现,其典型代码如下:
class RealSubject : Subject { public override void Request() { //业务方法具体实现代码 } }
代理类也是抽象主题类的子类,它维持一个对真实主题对象的引用,调用在真实主题中实现的业务方法,在调用时可以在原有业务方法的基础上附加一些新的方法来对功能进行扩充或约束,最简单的代理类实现代码如下:
class Proxy : Subject { private RealSubject realSubject = new RealSubject(); //维持一个对真实主题对象的引用 public void PreRequest() { …... } public override void Request() { PreRequest(); realSubject.Request(); //调用真实主题对象的方法 PostRequest(); } public void PostRequest() { …… } }
代理模式分类:
(1) 远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象
(2) 虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
(3) 保护代理(Protect Proxy):控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
(4) 缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
(5) 智能引用代理(Smart Reference Proxy):当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等。
15.3 代理模式应用实例
某软件公司承接了某信息咨询公司的收费商务信息查询系统的开发任务,该系统的基本需求如下:
(1) 在进行商务信息查询之前用户需要通过身份验证,只有合法用户才能够使用该查询系统;
(2) 在进行商务信息查询时系统需要记录查询日志,以便根据查询次数收取查询费用。
该软件公司开发人员已完成了商务信息查询模块的开发任务,现希望能够以一种松耦合的方式向原有系统增加身份验证和日志记录功能,客户端代码可以无区别地对待原始的商务信息查询模块和增加新功能之后的商务信息查询模块,而且可能在将来还要在该信息查询模块中增加一些新的功能。
1.实例分析及类图
通过分析,可以采用一种间接访问的方式来实现该商务信息查询系统的设计,在客户端对象和信息查询对象之间增加一个代理对象,让代理对象来实现身份验证和日志记录等功能,而无须直接对原有的商务信息查询对象进行修改,如图15-3所示:
图15-3 商务信息查询系统设计方案示意图
在图15-3中,客户端对象通过代理对象间接访问具有商务信息查询功能的真实对象,在代理对象中除了调用真实对象的商务信息查询功能外,还增加了身份验证和日志记录等功能。使用代理模式设计该商务信息查询系统,结构图如图15-4所示。
图15-4 商务信息查询系统结构图
15.5 虚拟代理 略
通过虚拟代理对象来间接引用真实对象,可以在一定程度上提高系统的性能。
15.6 缓冲代理
缓冲代理(Cache Proxy)也是一种较为常用的代理模式,它为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,从而可以避免某些方法的重复执行,优化系统性能。
在引入代理模式后,实现了在缓存级别上对业务对象的封装,增强了对业务对象的控制,如果需要访问的数据在缓存中已经存在,则无须再重复执行获取数据的方法,直接返回存储在缓存中的数据即可。由于原有业务对象(真实对象)和新增代理对象暴露在外的方法是一致的,因而对于调用方即客户端而言,调用代理对象与真实对象并没有实质的区别。
代理模式的主要缺点如下:
(1) 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。
(2) 实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理。
由图15-2可知,代理模式包含如下三个角色:
(1) Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口
(2) Proxy(代理主题角色):它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象;