代理模式
1)概述
1.定义
给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
2.作用
当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。
3.结构图
4.角色
-
Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口,在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。
-
Proxy(代理主题角色):它包含了对真实主题的引用,可以在任何时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主题;代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。
-
RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。
5.代码案例
抽象主题类
abstract class Subject{
public abstract void Request();
}
真实主题类
public class RealSubject extends Subject{
@Override
public void Request(){
//业务方法具体实现代码
}
}
代理类
public class Proxy extends Subject{
//维持一个对真实主题对象的引用
private RealSubject realSubject = new RealSubject();
public void PreRequest() {
//...
}
@Override
public void Request() {
PreRequest();
//调用真实主题对象的方法
realSubject.Request();
PostRequest();
}
public void PostRequest() {
//...
}
}
2)分类
远程代理(Remote Proxy):为一个位于不同地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中。
虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,可以先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
保护代理(Protect Proxy):控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
智能引用代理(Smart Reference Proxy):当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等。
3)简单案例
1.结构图
业务类AccessValidator用于验证用户身份,业务类Logger用于记录用户查询日志,Searcher充当抽象主题角色,RealSearcher充当真实主题角色,ProxySearcher充当代理主题角色。
2.代码案例
AccessValidator:身份验证类,业务类,它提供方法Validate()来实现身份验证。
public class AccessValidator {
//模拟实现登录验证
public boolean Validate(String userId) {
System.out.println("在数据库中验证用户'" + userId + "'是否是合法用户?");
if (userId.equals("杨过")) {
System.out.println("登录成功!"+userId);
return true;
} else {
System.out.println("登录失败!"+userId);
return false;
}
}
}
Logger:日志记录类,业务类,它提供方法Log()来保存日志。
public class Logger {
//模拟实现日志记录
public void Log(String userId) {
System.out.println("更新数据库,用户查询次数加1!用户为 "+userId);
}
}
Searcher:抽象查询类,充当抽象主题角色,它声明了DoSearch()方法。
public interface Searcher {
String DoSearch(String userId, String keyword);
}
RealSearcher:具体查询类,充当真实主题角色,它实现查询功能,提供方法DoSearch()来查询信息。
public class RealSearcher implements Searcher {
@Override
public String DoSearch(String userId, String keyword) {
System.out.println("用户="+userId+"使用关键词查询"+keyword+"商务信息!");
return "返回具体内容";
}
}
ProxySearcher:代理查询类,充当代理主题角色,它是查询代理,维持了对RealSearcher对象、AccessValidator对象和Logger对象的引用。
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.Validate(userId)) {
//调用真实主题对象的查询方法
String result = searcher.DoSearch(userId, keyword);
//记录查询日志
this.Log(userId);
//返回查询结果
return result;
} else {
return null;
}
}
//创建访问验证对象并调用其Validate()方法实现身份验证
public boolean Validate(String userId) {
validator = new AccessValidator();
return validator.Validate(userId);
}
//创建日志记录对象并调用其Log()方法实现日志记录
public void Log(String userId) {
logger = new Logger();
logger.Log(userId);
}
}
Program:客户端测试类
public class Program {
public static void main(String[] args) {
Searcher searcher;
searcher = new ProxySearcher();
String result = searcher.DoSearch("杨过", "玉女心经");
System.out.println(result);
}
}