设计模式系列(六)代理模式

来源:互联网 发布:如何黑进路由器 知乎 编辑:程序博客网 时间:2024/06/06 00:44

代理模式,就LZ目前的职业生涯中在spring中见到的代理模式是最多的。代理模式,就是为当前需要的对象创建一个代理对象,降低与当前对象的耦合。

先来个简单的静态代理。

一个女孩想要找对象,但是她的脸皮薄,不敢跟男孩接触。她的父母就帮她找了一个媒人负责安排她的相亲事宜。在这个故事中,媒人就是女孩这个对象的代理对象,他负责女孩的一切相亲事宜,女孩不用关心媒人怎么安排,只要展示自己就行了。

女孩和媒人都实现了相亲接口,实现了show方法,只不过女孩展示的是自己,媒人是负责把女孩展示出来顺带加点别的功能

public interface BlindDate {public void show();}

public class Girl implements BlindDate {@Overridepublic void show() {System.out.println("女孩展示自己");}}

public class MatchMaker implements BlindDate {BlindDate bd;MatchMaker(BlindDate bd){this.bd=bd;}@Overridepublic void show() {System.out.println("媒人牵线搭桥");bd.show();System.out.println("媒人收取中介费");}}
媒人持有一个实现了相亲接口的对象,并且在本身show方法中调用了持有对象的show方法,这样就完成了简单的对持有对象的show方法的加强。

public class Main {public static void main(String[] args) {//静态代理模式测试BlindDate girl=new Girl();BlindDate matchMaker=new MatchMaker(girl);matchMaker.show();      }}
这样一个男孩如果去找对象只需要调用媒人的方法,不必与女孩有直接的耦合。

就这样一个简单的静态代理就实现了,是不是感觉很简单啊,不要着急,难得还在后面呢。再来一个动态代理。

女孩还有相亲的接口还是一样,媒人类就不一样了。她这次不是提供show方法了,而是暴露了一个获得女孩代理对象的方法,这是什么鬼。在LZ看来还是那个核心思想,在获得对象之前已经给她增加好了功能了,到时候直接使用就是了。

public class DynamicMatchMaker {private Object girl;DynamicMatchMaker(Object girl) {this.girl = girl;}public Object getProxy() {return Proxy.newProxyInstance(girl.getClass().getClassLoader(),girl.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("媒人牵线搭桥");Object returnValue = method.invoke(girl, args);System.out.println("媒人收取中介费");return returnValue;}});}}
public class Main {public static void main(String[] args) {            BlindDate girl=new Girl();
girl=(BlindDate) new DynamicMatchMaker(girl).getProxy(); girl.show();
}
}

这样测试一下看看效果,是不是很棒棒。

有没有发现上面两种方式我们被代理的类都需要实现一个接口呀,如果你没发现,那么你要记住以后使用的时候要加上接口哦。在我们的实际开发中可无法保证每一个需要被代理的类都得实现接口。于是就出现了一个Cglib代理。

没有实现任何接口的女孩类

public class CGirl {public void show() {System.out.println("女孩展示自己");}}
public class CglibMatchMaker implements MethodInterceptor {private Object girl;CglibMatchMaker(Object girl){this.girl=girl;}    public Object getProxyInstance(){        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(girl.getClass());        enhancer.setCallback(this);        return enhancer.create();    }@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("媒人牵线搭桥");Object returnValue = method.invoke(girl, args);System.out.println("媒人收取中介费");return returnValue;}}
同样的,我们调用getProxyInstance()方法获得一个女孩对象。调用show()方法,同样可以实现功能
public class Main {public static void main(String[] args) {//Cglib代理测试CGirl cGirl=new CGirl();cGirl=(CGirl) new CglibMatchMaker(cGirl).getProxyInstance();cGirl.show();}}

需要注意的是,使用Cglib代理方式时一定要加上这两个jar包,jar包在源码中提供

看完这些代码你对代理模式有一点认识了么?衷心建议多敲代码,敲个几遍一定会理解的



最后奉上源码一份供大家参考。