生活随笔
收集整理的这篇文章主要介绍了
一天一种设计模式之五-----代理模式
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
2019独角兽企业重金招聘Python工程师标准>>>
一.代理模式简介
代理模式属于结构型模式
定义:代理模式为其他对象提供一种代理以控制对这个对象的访问。
代理模式是java框架层面应用最广泛的少数几种设计模式之一,非常重要。
适用场景:
远程代理,为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。
虚拟代理,根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的对象,这样可以达到性能优化;
安全代理,用来控制真实对象访问时的权限。一般用于对象应该有不同的访问权限的时候;
智能指引,是指当调用真实的对象的时候,代理处理另外的一些事情(用的比较多)
代理模式要求代理实现与被代理对象相同的接口(cglib与被代理对象是子类与父类的关系),以保证任何时候都能代替真实对象。这也是它与适配器模式的区别!!
代理模式广泛应用于aop编程。能够在不改变源代码的前提下提供统一的日志管理,前后置拦截器,符合开放封闭原则、依赖倒置原则,
二.测试代码
下面代码属于静态代理,大致场景是追求者会追妹子,但他不认识某girl,而通过代理类认识,所以追求者通过代理类对妹子展开了追求。
public class ProxyTest {public static void main(String[] args) {PursuitWay pursuitWay=new Proxy(new Pursuiter(new Girl("小白")));pursuitWay.giveFlower();pursuitWay.giveGift();}
}
interface PursuitWay{void giveFlower();void giveGift();
}
class Girl{private String name;public Girl(String name) {this.name=name;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
class Pursuiter implements PursuitWay{Girl girl;public Pursuiter(Girl girl){this.girl=girl;}@Overridepublic void giveFlower() {System.out.println("追求者送"+girl.getName()+"花");}@Overridepublic void giveGift() {System.out.println("追求者送"+girl.getName()+"礼物");}}class Proxy implements PursuitWay{PursuitWay pursuter;public Proxy(PursuitWay pursuiter){this.pursuter=pursuiter;}@Overridepublic void giveFlower() {pursuter.giveFlower();}@Overridepublic void giveGift() {pursuter.giveGift();}} 既然是通过代理去追妹子,那每次苦力活代理做做日志,设置个障碍就不难理解了吧。
上述功能如果要通过适配器模式实现,则proxy不必非要实现PursuitWay,它会有自己的方法而不必非要是giveXXX,只需要在它自己的方法中实现pursuter的giveXXX方法就可以了,具体代码略。
上述代理模式属于静态代理,因为代理类是我们自己编写出来的,而动态代理则是通过java虚拟机,在运行期间生成的字节码。
下述代码是通过动态代理实现的相同功能
1. 获取追求者上的所有接口列表;
2. 确定要生成的代理类的类名,默认为:com.sun.proxy.$ProxyXXXX ;
3. 根据需要实现的接口信息,在代码中动态创建 该Proxy类的字节码;
4 . 将对应的字节码转换为对应的class 对象;
5. 创建InvocationHandler 实例handler,用来处理Proxy所有方法调用;
6. Proxy 的class对象 以创建的handler对象为参数,实例化一个proxy对象
public class ProxyTest {public static void main(String[] args) {Class clazz=Proxy.getProxyClass(Pursuiter.class.getClassLoader(), Pursuiter.class.getInterfaces());System.out.println("proxy类为"+clazz.getName());System.out.println("proxy实现的接口有"+clazz.getInterfaces()[0].getName());System.out.println("-----开始生成代理对象(实际上该代理对象就是一个该接口的实现类)");PursuitWay pursuter=(PursuitWay) Proxy.newProxyInstance(Pursuiter.class.getClassLoader(), Pursuiter.class.getInterfaces(), new MyInvocationHandler(new Pursuiter(new Girl("小白"))));pursuter.giveFlower();pursuter.giveGift();}
}
interface PursuitWay{void giveFlower();void giveGift();
}
class Girl{private String name;public Girl(String name) {this.name=name;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
class Pursuiter implements PursuitWay{Girl girl;public Pursuiter(Girl girl){this.girl=girl;}@Overridepublic void giveFlower() {System.out.println("追求者送"+girl.getName()+"花");}@Overridepublic void giveGift() {System.out.println("追求者送"+girl.getName()+"礼物");}}
class MyInvocationHandler implements InvocationHandler{Object object;public MyInvocationHandler(Object object){this.object=object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {return method.invoke(object, args);}} 上述代码通过jdk自带的代理类实现,它和静态代理类有同样的局限性,就是要求被代理类必须有一个或者多个对应具体业务逻辑的接口。myInvocationHandler里边的invoke方法中可以提供拦截、写日志等功能。
cglib包的代理类CglibProxy是针对某个类生成一个子类,该子类自然会包括其父类的所有业务逻辑方法。而且不在局限于必须有上层接口。但是cglib包也要求被代理类不能为final类,否则继承不了,测试代码和动态代理很像,略。
cglib底层采用ASM字节码生成框架,使用字节码技术生成代理类,理论上比使用Java反射效率要高,不过有大神曾经测试过,貌似性能差不多,而且jdk的动态代理还要比cglib效率高一点点。有兴趣的朋友可以去试试。
欢迎大神交流意见。
下一节将会讲解工厂方法模式,该模式在service层应用很普遍。敬请期待。
转载于:https://my.oschina.net/u/2323537/blog/634874
总结
以上是生活随笔为你收集整理的一天一种设计模式之五-----代理模式的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。