简介
代理模式是指为一些对象提供一个代理来控制外部对于这些对象的访问。这样避免了客户端直接访问外部对象。
代理模式在生活中非常的常见,中介也是代理的一种。代理不止可以提供对对象的控制也可以扩充访问对象本身的功能。
在JAVA中代理模式根据代理类生成的时机又可以分为静态代理和动态代理,静态代理代理类在编译期生成,而动态代理代理类在Java运行时动态生成。
适用场景
(1)当客户端对象需要访问远程主机中的对象时可以使用远程代理。
(2)当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。
(3)当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理。通过使用缓冲代理,系统无须在客户端每一次访问时都重新执行操作,只需直接从临时缓冲区获取操作结果即可。
(4)当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理。
(5)当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。
代理模式结构
代理模式主要由三部分构成:
- 抽象主题类:定义开放给代理类的真正主题类接口。
- 真正主题类:实现抽象主题类中的接口功能,是被代理对象
- 代理类:提供与真实主题相同的接口,其内部含有对真实主题的引用,可以访问、控制、扩展真实主题的功能
案例
这里我举一个非常简单的例子,就是对服务器通过代理做一个访问控制,由代理来管理服务器权限,当然在实际中的访问控制比这个要复杂的多
静态代理
抽象主题类
public interface ServerInterface {
void access();
void setLevel(int i);
}
真正主题类
public class Server implements ServerInterface{
@Override
public void access() {
System.out.println("访问成功");
}
//服务器不负责权限控制
@Override
public void setLevel(int i) {
}
}
代理类
public class ServerProxy implements ServerInterface{
private Server server=new Server();
private int level=0;
@Override
public void access() {
if(level<3){
System.out.println("权限不足");
return ;
}
System.out.println("权限验证通过");
server.access();
}
@Override
public void setLevel(int i) {
this.level=i;
}
}
测试
@Test
public void proxy()
{
ServerProxy serverProxy=new ServerProxy();
serverProxy.setLevel(3);
serverProxy.access();
}
测试结果
权限验证通过
访问成功
动态代理
关于动态代理的原理我这里不做介绍,常用的JAVA动态代理也有JDK与CGlib两种方式,我这里写一下JDK动态代理的实现方法。
抽象主题类和具体主题类和上面一致
代理类
public class ServerProxyFactory {
private int level=0;
private Server server=new Server();
public ServerInterface getProxyObject(){
ServerInterface serverInterface = (ServerInterface) Proxy.newProxyInstance(server.getClass().getClassLoader(), server.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("setLevel")) {
level=(int)args[0];
System.out.println("权限等级设为:"+level);
}
if(method.getName().equals("access")){
if(level<3){
System.out.println("权限不足");
return null;
}
System.out.println("权限通过,允许访问");
}
Object obj = method.invoke(server, args);
return obj;
}
});
return serverInterface;
}
}
测试类
@Test
public void proxy()
{
ServerProxyFactory serverProxyFactory=new ServerProxyFactory();
ServerInterface proxyObject = serverProxyFactory.getProxyObject();
proxyObject.setLevel(1);
proxyObject.access();
}
测试结果
权限等级设为:1
权限不足
总结
代理模式的应用在实际中非常多,这里无法全部一一介绍,每个代理模式应用的具体实现也可能会有较大的区别,不过通过案例也可以了解到,代理模式本身相当于在客户端与目标对象直接额外增加一层关口,可以起到管控的作用也可以起到扩展的作用。