个人认为代理模式还是比较麻烦的一章,尤其是视频上关于动态代理的东西,还要用到反射什么的,是需要认真学习的一章。
下面通过举例来讲解一下代理模式。
例子是这样的:假设一个搜索引擎有偿为用户提供搜索服务,所以用户分为普通用户和黄金用户,只有黄金用户才能通过此引擎进行查询,另外引擎还具有统计搜索次数的功能。
Test.java
public class Test {
public static void main(String[] args) {
//黄金用户like
User like = new User("like",User.GOLD);
//黄金用户god
User god = new User("god", User.GOLD);
//普通用户sb
User sb = new User("sb", User.REGULAR);
Object o = Proxy.factory(new RealSearch());
Search s = (Search)o;
s.search(like);
s.search(god);
s.search(sb);
}
}
这个类模拟了三个用户,两个黄金用户和一个普通用户,分别执行查询方法。
Search.java
public interface Search {
public void search(User user);
}
这是一个搜索接口。
RealSearch.java
public class RealSearch implements Search {
@Override
public void search(User user) {
System.out.println(user.getName() + ":I'm searching");
}
}
实现了搜索接口的现实搜索类,这里只有搜索方法,并没有提供拦截和统计。
AccessStatistics.java
public class AccessStatistics {
private int count;//用来记录搜索次数
private Map<Integer, String> details = new HashMap<Integer, String>();//记录搜索详细信息
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Map<Integer, String> getDetails() {
return details;
}
public void setDetails(Map<Integer, String> details) {
this.details = details;
}
public AccessStatistics() {
super();
}
public AccessStatistics(int count, Map<Integer, String> details) {
super();
this.count = count;
this.details = details;
}
public void access(User user){
this.count += 1;
this.details.put(count, user.getName());
}
}
这个类主要用来统计搜索次数。
AccessValidator.java
public class AccessValidator {
public AccessValidator() {
super();
}
public boolean canSearch(User user){
if(user.getType().equals(User.GOLD)){
return true;
}else{
return false;
}
}
}
这个类用来判断用户是否有资格进行查询。
Proxy.java
public class Proxy implements InvocationHandler {
private Object object;
private AccessStatistics as = new AccessStatistics();
private AccessValidator av = new AccessValidator();
public Proxy(){
}
public Proxy(Object object){
this.object = object;
}
//静态工厂类,用来产生代理对象
public static Object factory(Object object){
Class<? extends Object> cls = object.getClass();
return java.lang.reflect.Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), new Proxy(object));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
User user = (User) args[0];
Object o = null;
//此处过滤用户
if(canSearch(user)){
o = method.invoke(object, args);
//此处进行统计
statictis(user);
}else{
System.out.println("你没有权限执行查询操作!");
}
return o;
}
public boolean canSearch(User user){
return av.canSearch(user);
}
public void statictis(User user){
as.access(user);
System.out.println("您是第"+as.getCount()+"个查询者");
}
}
这是一个动态代理类,为Search代理。
三. 总结