代理模式又叫委托模式,类图如下:
三个角色的定义:
抽象主题角色(subject): 抽象主题类一个普通的业务类型,可以是抽象类也可以是接口。
1 //抽象角色 2 public abstract class Subject { 3 public abstract void request(); 4 }
具体主题角色(realsubject): 被代理角色,业务逻辑的具体执行者。
1 //真实角色 2 public class RealSubject extends Subject{ 3 @Override 4 public void request() { 5 //此处实现父类方法 6 } 7 }
代理主体角色(proxy): 代理类,负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色,可以在需要的时候创建或删除具体主题对象。一般在真实主题角色处理完毕前后还要做些预处理和善后工作。核心功能都在这个类中
1 //代理角色 2 public class ProxySubject extends Subject(){ 3 private RealSubject realSubject;//私有RealSubject 4 5 @Override 6 public void request() { 7 preRequest(); 8 if(realSubject==null){ 9 realSubject = new RealSubject(); 10 } 11 realSubject.request();//执行RealSubject的request方法 12 postRequest(); 13 } 14 15 private void postRequest() { 16 //善后工作 17 } 18 19 private void preRequest() { 20 //预处理 21 } 22 }
但是这种实现方式有个较大缺点,如果Subject接口发生变化,代理类和具体实现类都要一起变化以适应新接口。
动态代理:
Java对代理模式提供了内建支持,java.lang.reflect.Proxy类和InvocationHandler接口。
Proxy类核心方法:Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 用于反射调用
接口方法:Object invoke(Object proxy,Method method, Object[] args) 用于回调
下面代码省略了无参构造器
1 //代理类的增强版(动态代理): 2 public class ProxyHandler implements InvocationHandler { 3 private Object proxied; 4 5 // 反射要用到的核心构造 6 public ProxyHandler(Object proxied) { 7 this.proxied = proxied; 8 } 9 10 // 实现接口方法 11 public Object invoke(Object proxy, Method method, Object[] args) 12 throws Throwable { 13 postRequest(); 14 // 反射调用实际方法 15 Object object = method.invoke(proxied, args); 16 preRequest(); 17 return object; 18 } 19 20 private void postRequest() { 21 // 善后工作 22 } 23 24 private void preRequest() { 25 // 预处理 26 } 27 }
此处用到了Java的反射机制:
1 //客户端代码: 2 public class Client { 3 public static void main(String[] args) { 4 RealSubject real = new RealSubject(); 5 //反射代理类的构造方法创建代理对象 6 Subject proxySubject = (Subject) Proxy.newProxyInstance( 7 Subject.class.getClassLoader(), new Class[] { Subject.class }, 8 new ProxyHandler(real)); 9 //使用代理对象 10 proxySubject.request(); 11 } 12 }
总结:
代理模式的本质:控制对象访问。
通过代理目标对象连接客户和目标对象引入间接性实现了具体对象调用前后的各种附加操作,甚至可以完全不去使用目标对象。
在方法执行前后对调用进行拦截,并创建自己行为的思想属于面向切面编程(AOP)。