代理模式也叫委托模式,是一种结构型设计模式。为其他对象提供一种代理,以控制对这个对象的访问。那么什么时候使用代理模式呢?当无法或者不想直接访问某个对象时,或者访问某个对象有困难时,可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。
1 创建一个共同的接口
package proxypattern;
public abstract class Subject {
/**普通的业务方法*/
public abstract void visit();
}
2 创建一个真实对象的类
package proxypattern;
public class RealSubject extends Subject{
@Override
public void visit() {
//实现具体逻辑
System.out.println("RealSubject---");
}
}
3 创建一个代理类,在其中声明真实主题类型的变量
package proxypattern;
public class ProxySubject extends Subject{
private RealSubject mSubject;
public ProxySubject(RealSubject mSubject) {
super();
this.mSubject = mSubject;
}
@Override
public void visit() {
//通过真实主题引用的对象,调用真实主题中的逻辑方法
mSubject.visit();
}
}
4 通过代理类调用真实主题的对象
package proxypattern;
public class Client {
public static void main(String[] args) {
//构造真实主题的对象
RealSubject realSubject = new RealSubject();
//通过真实主题对象构造一个代理对象
ProxySubject proxySubject = new ProxySubject(realSubject);
//调用代理对象的方法,间接调用真实主题的业务逻辑
proxySubject.visit();
}
}
输出结果:RealSubject--Method----
以上的代理模式为静态代理模式,就是代理类所代理的对象的类型是固定的;此外,我们还可以更加灵活地处理被代理对象的类型,这是动态代理模式:
首先创建一个动态代理类:
package proxypattern;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理类
*/
public class DynamicProxy implements InvocationHandler{
//被代理的类 的引用
private Object object;
/**
* 在构造方法中初始化引用对象
* @param object
*/
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//调用被代理对象的方法
Object invoke = method.invoke(object, args);
return invoke;
}
}
通过Java中的Proxy类,获取一个RealSubject实现的接口类型一致的代理类,再通过这个代理类调用被代理对象的方法:
package proxypattern;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
//1 构造一个被代理对象
Subject subject = new RealSubject();
//2 获取被代理类的ClassLoader
ClassLoader loader = subject.getClass().getClassLoader();
//3 构造一个动态代理
DynamicProxy proxy = new DynamicProxy(subject);
//4 通过loader构造一个代理对象
Subject proxyInstance = (Subject) Proxy.newProxyInstance(loader, new Class[]{Subject.class}, proxy);
//5 代理对象调用被代理对象的方法
proxyInstance.visit();
}
}
输出结果:RealSubject--Method----