模式动机及定义
模式动机
在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现
间接引用。代理对象可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去掉客户不能看
到的内容和服务或者添加客户需要的额外服务。
通过引入一个新的对象(如远程代理对象)来实现对真实对象的操作或者将新的对象作为真实对象的一个替
身,这种实现机制即为代理模式,通过引入代理对象来间接访问一个对象,这就是代理模式的模式动机。
模式定义
代理模式(Proxy Pattern):给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的
英文叫做Proxy或Surrogate,它是一种对象结构型模式。
模式结构与分析
模式结构
模式的结构图如下:
代理模式包含如下角色:
- Subject:抽象主题角色
- Proxy:代理主题角色
- RealSubject:真实主题角色
模式分析
代理模式示意结构图比较简单,一般可以简化为如下图所示,但是在现实中要复杂很多。
典型的代理类实现代码如下:
public class Proxy implements Subject {
private RealSubject realSubject = new RealSubject();
public void preRequest(){......}
public void request() {
preRequest();
realSubject.request();
postRequest();
}
public void postRequest(){......}
}
模式实例与解析
模式实例与解析
实例一:收费商务信息查询系统
在某软件公司承接了某信息咨询公司的收费商务信息查询系统的开发任务,该系统的基本需求如下:
(1) 在进行商务信息查询之前用户需要通过身份验证,只有合法用户才能够使用该查询系统;
(2) 在进行商务信息查询时系统需要记录查询日志,以便根据查询次数收取查询费用。
该软件公司开发人员已完成了商务信息查询模块的开发任务,现希望能够以一种松耦合的方式向原有系统增
加身份验证和日志记录功能,客户端代码可以无区别地对待原始的商务信息查询模块和增加新功能之后的商
务信息查询模块,而且可能在将来还要在该信息查询模块中增加一些新的功能。
试使用代理模式设计并实现该收费商务信息查询系统。
参考代码如下:
public class AccessValidator {
public boolean Validate(String userId) {
System.out.print("在数据库中验证用户" + userId + "是否是合法用户?");
if (userId.equals("杨过")) {
System.out.print(userId + "登录成功");
return true;
} else {
System.out.print(userId + "登录失败");
return false;
}
}
}
public class Logger {
public void Log(String userId) {
System.out.println(userId + "更新数据库,用户查询次数加1");
}
}
public interface Searcher {
String DoSearch(String userId, String keyword);
}
public class RealSearcher implements Searcher {
public String DoSearch(String userId, String keyword) {
System.out.print(userId + "用户使用关键词" + keyword + "查询商务信息");
return "返回具体内容";
}
}
public class ProxySearcher implements Searcher {
private RealSearcher searcher = new RealSearcher();
private AccessValidator validator;
private Logger logger;
public String DoSearch(String userId, String keyword) {
//如果身份验证成功,则执行查询
if (this.validator(userId)) {
String result = searcher.DoSearch(userId, keyword);
this.Log(userId);
return result;
}
return null;
}
private void Log(String userId) {
logger = new Logger();
logger.Log(userId);
}
private boolean validator(String userId) {
validator = new AccessValidator();
return validator.Validate(userId);
}
}
模式效果
代理模式的优点:
- 代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;
- 远程代理使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可 以快速响应并处理客户端请求;
- 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运 行速度;
- 保护代理可以控制对真实对象的使用权限。
代理模式的缺点:
- 由于再客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变 慢;
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。