代理设计模式,是一种常用的设计模式。顾名思义,在面向对象的世界中,就是一个对象对另一个对象的代理。
如现实生活中,处处都是代理,中介是对业主的代理,王婆是对金莲的代理,经纪人至于艺人的代理,销售代理等,当然这是通俗代理。
代理对外是代理对象去交互,但是真正完成工作的,往往又是被代理的对象。例如租房,找中介,但是真正租到的是业主的房子。xxx找王婆,但是最终干活的是金莲。找艺人拍戏,找的是经纪人,但最终拍戏的是艺人等等。
为什么要这样做呢?
对于代理对象,提供比较单一的功能,且可以在代理增加需要的逻辑,却不影响被代理对象。如经纪人帮艺人包装等。
对于被代理对象,控制被代理对象的访问权限,被代理对象只提供部分需要的功能。如中介只代理业主的房子。如果啥都让业主做的话,业主的事情会非常多,而表现在程序上,就是对象的功能非常复杂。
在程序设计模式中,代理模式又可以分为静态代理,动态代理。
静态代理
通过代码来熟悉静态代理,下面是一个静态代理的例子,首先有个IPrettyGirl接口,有三个方法chat,enjoy,sleep三个方法
public interface IPrettyGirl {
void chat();
void enjoy();
void sleep();
}
接口有一个实现
public class JinLian implements IPrettyGirl {
@Override
public void chat() {
System.out.println("to chat with "+this.getClass().getSimpleName());
}
@Override
public void enjoy() {
System.out.println("to enjoy with "+this.getClass().getSimpleName());
}
@Override
public void sleep() {
System.out.println("to sleep with "+this.getClass().getSimpleName());
}
}
有一个代理类Wangpo,代理IPrettyGirl的chat和enjoy方法。毕竟sleep是违法的,不能做这事。
public class WangPo {
private IPrettyGirl prettyGirl;
public WangPo(IPrettyGirl prettyGirl){
this.prettyGirl = prettyGirl;
}
public void chat(){
this.prettyGirl.chat();
System.out.println("I am "+this.getClass().getSimpleName()+", I Completed a chat order");
}
public void enjoy(){
this.prettyGirl.enjoy();
System.out.println("I am "+this.getClass().getSimpleName()+", I Completed a enjoy order");
}
}
这时候大官人要来找乐子了,怎么找呢,不用找金莲,有武松在太危险了,直接找王婆就可以了。
public class XiMenDaGuanRen {
public static void main(String[] args) {
IPrettyGirl prettyGirl = new JinLian();
WangPo wangPo = new WangPo(prettyGirl);
wangPo.chat();
wangPo.enjoy();
}
}
这样就实现了一个经典的静态代理,通过面向接口编程,王婆可以代理所有的漂亮女孩(实现了IPrettyGir接口的对象)。但是为什么是静态代理呢,因为这中代理,要找女孩的话,需要提前的编写代理类去代理IPrettyGirl的对象。这样的话,在某些情况下,也是不方便的。这个时候就需要动态代理了。
动态代理
同样通过代码和实例理解什么是动态代理。西门大官人整天找王婆,难免会让旁人发现问题。但是大官人还是要找乐子,如果自己重新找个代理就好了。这个时候就可以用动态代理,自己创建代理,就可以随时享乐了。
public class XiMenDaGuanRen {
public static void main(String[] args) {
IPrettyGirl prettyGirl = (IPrettyGirl) Proxy.newProxyInstance(XiMenDaGuanRen.class.getClassLoader(), new Class[]{IPrettyGirl.class}, new ProxyInvocationHandler(new JinLian()));
prettyGirl.chat();
prettyGirl.enjoy();
}
}
class ProxyInvocationHandler implements InvocationHandler{
private Object object;
public ProxyInvocationHandler(Object obj){
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before service");
Object obj = method.invoke(this.object, args);
System.out.println("after service");
return obj;
}
}
动态代理有一套特定的API,动态代理不需要编写特定的代理类,可以使用代码动态创建代理类,只需要知道代理类的对象和类型即可。现在对代理,静态代理,动态代理应该有了初步的了解了。
再来看看JDK动态代理涉及到的Java API
Proxy,提供创建动态代理类和对象的静态方法,也是这些方法创建的所有动态代理类的超类。
InvocationHandler,代理类实例的Invocation Handler实现的接口。每一个代理类的实例,都有一个关联的调用处理程序,调用代理实例的invoke方法时,方法调用会被转发到代理实例InvocationHandler来执行。
cglib动态代理
上面这些是JDK的动态代理,第三方库cglib也提供了动态代理的实现方式,再了解一下cglib的动态代理。
通过代码来了解一下,直接看怎么使用cglib实现动态代理。
public class XiMenDaGuanRen {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(JinLian.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before service");
Object obj = methodProxy.invokeSuper(o, objects);
System.out.println("before service");
return obj;
}
});
JinLian jinLian = (JinLian) enhancer.create();
jinLian.enjoy();
jinLian.chat();
}
}
看起来大同小异,cglib的关键api,cglib相比较jdk的动态代理,可以代理类,而jdk只能代理接口。
Enhancer,生成动态子类以实现方法拦截,最初是作为JDK1.3自带动态代理的另外一种支持,带允许扩展具体的基类,也可以实现接口,动态生成的子类,重写父类的非final方法,并回调到用户自定义的拦截器。
MethodInterceptor,方法拦截器,代理类的CallBack实现的接口,代理类的方法调用被转发到回调来执行。
(^_^)