智能引用代理
本章所述是来自真实的华尔款街金融网站项目,在本站要实现两个基本功能:一是必须对用户进行身份检查,二是对用户搜索次数进行统计,以便按照收费标准进行收费.在这里要用到两种模式:保护代理和智能代理。一个代理对象对调用被代理对象的用户进行权限检查,并且只允许有适当权限的用户调用原对象,这样的代理对象叫做保护代理。所谓智能引用代理,就是一个代理对象对调用原对象的用户进行统计计数.
一:系统设计步骤
(A)抽象和具体的划分
首先,系统需要一个能进行查询的类,但是有经验的设计师不会仅仅给出一个具体类就交差,因为设计师必须考虑到查询功能在今后可能会有变化,因此一个好的设计师必须使系统可以在最小的改动下进行最大的扩充.所以应当有一个抽象和一个具体角色,抽象角色给出接口的声明,而将实现的细节交给具体的角色.这样如果在将来需要有新的查询功能,只需要创建一个新的具体角色就好了,而无需改变抽象角色.我们这里抽象角色由Java的接口(Searcher)扮演,个体角色由一个类(RealSearcher)扮演.
(B)辅助功能的提供
当然,系统必须有两个辅助对象,一个用于检查用户权限,为AccessValidator,另一个用做查询的计数器,为UsageLogger。这两个辅助对象分别提供适当的方法检查用户的权限和将查询事件记录到数据库中。一般而言,稍有经验的设计师都会想到使用独立的对象负责这两项责任,而不是由负责查询的Searcher或者RealSearcher负责所有的责任.
(C)引入代理角色
基本的功能现在都有确定的对象提供了:查询功能由RealSearch对象提供,检查用户权限的功能由AccessValidator提供,记录查询次数的功能由UsageLogger对象提供.
一个没有代理模式知识和应用代理模式的设计师往往就在这里停下来了,因为人们往往会认为只要修改一下RealSearcher对象的方法,在查询操作之前进行权限的检查,在查询之后进行查询次数的记录就可以了。当然是可以的,只是不够好,为什么?因为对权限的检查和记录调用次数的责任属于RealSearcher对象的调用控制,这个责任应当与RealSearcher对象本身分开.换言之,系统应当对RealSearcher对象提供一个代理对象,由代理对象负责这两项工作,并将调用委派给RealSearcher对象.代理对象Proxy持有RealSearcher对象,AccessValidator对象和UsageLogger对象的引用.
二:系统的时序
(A)客户端调用代理对象
(B)代理对象调用AccessValidator对象,确定用户确实具有的相应的权限
(C)代理对象调用RealSearcher对象,完成查询功能
(D)代理对象调用UsageLogger对象,完成计数功能
(E)代理对象将RealSearcher对象的查询结果返回给客户端
源代码如下:
package cai.milenfan.basic.test; public class Client { //申明一个静态变量searcher private static Searcher searcher; public static void main(String[] args){ //此变量的真实类型为Proxy,这就保证了客户端不能分辨RealSearcher和Proxy,这是代理模式的用意之一searcher = new Proxy(); String userId="Admin"; String searchType="SEARCH_BY_ACCOUNT_NUMBER"; String result = searcher.doSearch(userId,searchType); System.out.println(result); } }