代理模式分为静态代理和动态代理,静态代理比较简单,动态代理要用到反射机制
静态代理的例子:
日常生活中,想要联系明星出演节目,往往不是通过直接联系明星,而是联系明星的经纪人,也就是代理
UML图如下
不管是明星(SuperStar)还是经纪人(Broker)都实现Star接口,通过操作接口来和经纪人对接
Star接口代码
package cn.designmodel.proxy.staticProxy; /** * 抽象角色,提供代理角色和真实角色对外公共方法 */ public interface Star { void perform(); }
SuperStar代码
package cn.designmodel.proxy.staticProxy; public class SuperStar implements Star { @Override public void perform() { System.out.println("明星表演节目"); } }
Broker代码
package cn.designmodel.proxy.staticProxy; public class Broker implements Star { private Star superStar; public Broker(Star s) { this.superStar = s; } @Override public void perform() { superStar.perform(); } }
最后是测试程序代码
package cn.designmodel.proxy.staticProxy; public class TestStaticProxy { public static void main(String[] args) { Star zjy = new SuperStar(); Star jjr = new Broker(zjy); jjr.perform(); } }
运行结果
明星表演节目
可以看出,通过经纪人(jjr)表演,实现明星(zjy)的表演,这就是静态代理模式
动态代理的例子:
比如有个业务A和业务B,不管执行哪个业务,在执行前和执行完都需要有个记录,很像Spring里的切面一样。
业务接口代码
public interface AbstractSubject { public void request(); }
业务A和业务B代码
public class RealSubjectA implements AbstractSubject { public void request() { System.out.println("真实主题类A!"); } } public class RealSubjectB implements AbstractSubject { public void request() { System.out.println("真实主题类B!"); } }
动态代理类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class DynamicProxy implements InvocationHandler { private Object obj; public DynamicProxy(){} public DynamicProxy(Object obj) { this.obj=obj; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { preRequest(); method.invoke(obj, args); postRequest(); return null; } public void preRequest(){ System.out.println("调用之前!"); } public void postRequest(){ System.out.println("调用之后!"); } }
最后是测试代码
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Client { public static void main(String args[]) { InvocationHandler handler =null; AbstractSubject subject=null; handler=new DynamicProxy(new RealSubjectA()); subject=(AbstractSubject)Proxy.newProxyInstance(AbstractSubject.class.getClassLoader(), new Class[]{AbstractSubject.class}, handler); subject.request(); System.out.println("------------------------------"); handler=new DynamicProxy(new RealSubjectB()); subject=(AbstractSubject)Proxy.newProxyInstance(AbstractSubject.class.getClassLoader(), new Class[]{AbstractSubject.class}, handler); subject.request(); } }
运行结果
调用之前!
真实主题类A!
调用之后!
------------------------------
调用之前!
真实主题类B!
调用之后!
对于动态代理,我还有些困惑,写得不是很详细,正在慢慢学习中。。