代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。代理对象可以在客户端和目标对象之间起到中介的作用。代理对象可以完成比原对象更多的职责,当需要为原对象添加横切关注功能时,就可以使用原对象的代理对象。
好处:职责清晰、降低系统耦合、提高扩展性
代理(Proxy)是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。
代理模式涉及的对象:抽象角色(公共接口)、真实角色(被代理类)、代理角色(代理类)
代理模式有两种实现的方式,一种是静态代理,另一种是动态代理。
静态代理
代理对象是由程序猿创建的,而且一个Proxy一般就只能代理一类目标对象(实现共同Subject接口),相当于代理类和被代理类关系提前要确定。
代理接口
public interface Subject {
void action();
}
目标对象实现接口
public class RealASubject implements Subject {
@Override
public void action() {
System.out.println("********* realASubject");
}
}
public class RealBSubject implements Subject {
@Override
public void action() {
System.out.println("********* realBSubject");
}
}
代理对象
public class ProxySubject implements Subject{
private Subject subject;
public ProxySubject(Subject subject){
this.subject = subject;
}
@Override
public void action() {
subject.action();
}
}
调用
public class Client {
public static void main(String[] args) {
ProxySubject subjectA = new ProxySubject(new RealASubject());
subjectA.action();
ProxySubject subjectB = new ProxySubject(new RealBSubject());
subjectB.action();
}
}
结果
动态代理
动态代理是根据代理的对象,动态创建代理类。避免静态代理中代理类接口过多的问题。动态代理是通过反射来实现的,借助Java自带的java.lang.reflect.Proxy
,通过固定的规则生成。
动态代理实现时的代理接口与接口实现与静态代理相同,区别开始是第三步创建代理类。
public class DynamicProxy implements InvocationHandler {
private Object object;
public DynamicProxy(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res = method.invoke(object, args);
return res;
}
}
调用
public class Client {
public static void main(String[] args) {
Subject realASubject = new RealASubject();
DynamicProxy proxy = new DynamicProxy(realASubject);
ClassLoader classLoader = realASubject.getClass().getClassLoader();
Subject subjectA = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, proxy);
subjectA.action();
}
结果
要求:
为ArrayList创建一个动态代理类
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
List<String> p = (List<String>) Proxy.newProxyInstance(list.getClass().getClassLoader(), list.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(list, args);
}
});
p.add("哈哈");
System.out.println(list);
}