标签:
代理模式就是为另一个对象提供一个替身,来控制对这个对象的访问。
一开始觉得代理没有有什么作用,觉得代理也只是调用了真实对象的方法,后来才知道,代理的用处还是挺大的。
比如说,代理可以控制不同人对于同一个对象的访问,控制他们使用的权限,称为保护代理。代理还可以作为另一个JVM上对象的本地代表,客户端需要请求数据的时候,由代理利用网络转发到远程执行,并且结果会通过网络返回给代理,由代理将结果返回给用户,称为远程代理。当访问的对象需要很大的开销,这时候代理可以作为其代表,到了需要对象的时候才创建它,称为虚拟代理,例如浏览网页时,通常加载图片需要很长的时间,在未加载完成前,代理可以先显示“加载中”或者默认的图片,等到加载完成了,代理显示真正的图片。
代理模式的类图如下:

Java在java.lang.reflect包中有自己的代理支持,实际的代理类是在运行时创建的,所以称为动态代理,动态代理的类图和普通的代理类图不一样。

现在我们利用java提供的代理类,来实现对对象访问的控制。
假设有一个约会网站,每个人可以对自己的信息修改,但不能设置自己的评分,其他人可以设置评分,但不能修改信息。
类图如下:

PersonBean接口,就是RealSubject和Proxy都实现的接口
public interface PersonBean
{
public String getName();
public String getGender();
public int getHotOrNotRate();
public void setName(String name);
public void setGender(String gender);
public void setHotOrNotRate(int rate);
}
PersonBeanImpl类,就是real subject类
public class PersonBeanImpl implements PersonBean
{
private String name;
private String gender;
private int rate;
public String getName()
{
return name;
}
public String getGender()
{
return gender;
}
public int getHotOrNotRate()
{
return rate;
}
public void setName(String name)
{
this.name=name;
}
public void setGender(String gender)
{
this.gender=gender;
}
public void setHotOrNotRate(int rate)
{
this.rate=rate;
}
}
控制本人操作的OwnerInvocationHandler
import java.lang.reflect.*;
public class OwnerInvocationHandler implements InvocationHandler
{
PersonBean person;
public OwnerInvocationHandler(PersonBean person)
{
this.person=person;
}
public Object invoke(Object proxy,Method method,Object[] args)throws Exception
{
if(method.getName().startsWith("get"))//如果调用的是get方法
{
return method.invoke(person,args);//直接调用方法
}
else if(method.getName().startsWith("set"))//如果调用的是set方法
{
if(method.getName().equals("setHotOrNotRate"))//如果调用的是设置评分的方法
{
throw new IllegalAccessException();//抛出异常
}
else
{
return method.invoke(person,args);//直接调用
}
}
return null;
}
}
控制非本人操作的NotOwnerInvocationHandler
public class NoOwnerInvocationHandler implements InvocationHandler
{
PersonBean person;
public NoOwnerInvocationHandler(PersonBean person)
{
this.person=person;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Exception
{
if(method.getName().startsWith("get"))//如果调用的是get方法
{
return method.invoke(person,args);//直接调用方法
}
else if(method.getName().startsWith("set"))//如果调用的是set方法
{
if(method.getName().equals("setHotOrNotRate"))//如果调用的是设置评分的方法
{
return method.invoke(person,args);//直接调用
}
else
{
throw new IllegalAccessException();//抛出异常
}
}
return null;
}
}
负责产生Proxy对象的工厂
public class HandlerFactory
{
public static PersonBean getOwnerProxy(PersonBean person)
{
return (PersonBean)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new OwnerInvocationHandler(person));
}
public static PersonBean getNoOwnerProxy(PersonBean person)
{
return (PersonBean)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new NoOwnerInvocationHandler(person));
}
}
测试类
public class Test
{
public static void main(String[] args)
{
PersonBean judy=getPersonFromDatabase("judy");
PersonBean ownProxy=HandlerFactory.getOwnerProxy(judy);
System.out.println("name:"+ownProxy.getName());
System.out.println("gender:"+ownProxy.getGender());
System.out.println("Rate:"+ownProxy.getHotOrNotRate());
try
{
ownProxy.setHotOrNotRate(10000);
}
catch(Exception e)
{
System.out.println("You can‘t set your own rate!");
}
PersonBean noOwnProxy=HandlerFactory.getNoOwnerProxy(judy);
System.out.println("I am Jenny.I am dating Judy.");
System.out.println("name:"+noOwnProxy.getName());
System.out.println("gender:"+noOwnProxy.getGender());
System.out.println("Rate:"+noOwnProxy.getHotOrNotRate());
System.out.println("change Judy‘s rate to 90");
noOwnProxy.setHotOrNotRate(90);
System.out.println("Now Judy‘s Rate:"+noOwnProxy.getHotOrNotRate());
try
{
noOwnProxy.setName("ChenHaiqing");
}
catch(Exception e)
{
System.out.println("You have no access to change her infomation.");
}
}
/**
模拟从数据库中提取数据
**/
public static PersonBean getPersonFromDatabase(String name)
{
PersonBean person=new PersonBeanImpl();
person.setName(name);
person.setGender("male");
person.setHotOrNotRate(100);
return person;
}
}
运行结果:

可以看到,当Judy尝试改变自己的评分时,就会出现“You can‘t set your own rate!”,当Jenny尝试改变Judy的个人信息时,就会出现"No access!"
代理模式控制了对象的访问,但是proxy类到底是什么时候生成的呢?可以看看工厂里的代码。
public static PersonBean getOwnerProxy(PersonBean person)
{
return (PersonBean)Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new OwnerInvocationHandler(person));
}
调用了Proxy的静态方法,相当于生成了Proxy类并返回其对象,而且把它和InvocationHandler联系在一起。
当客户端调用proxy.getName()方法时,proxy会接着调用InvocationHandler的invoke方法,由它来决定如何处置这一请求,可以转发给RealSubject,遇到没有权限的操作则抛出异常。
代理模式应用范围很广,请看下图:

标签:
原文地址:http://www.cnblogs.com/qingfei1994/p/4271848.html