博客
关于我
厚积薄发打卡Day36 :[itcast] GoF23通俗易懂的设计模式之 <代理模式>
阅读量:370 次
发布时间:2019-03-04

本文共 3301 字,大约阅读时间需要 11 分钟。

代理模式

概述

代理模式(Proxy)为其他对象提供一种代理以控制对这个对象的访问。由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

静态代理

静态代理的特点是代理类在编译期就生成。常见的例子是火车站卖票的场景。顾客通过代售点购买火车票,实际上仍然是火车站卖票。类图如下:

+------------+| 代售点    |+------------+|          || 卖票方法 ||          |+------------+

实例说明:

public interface SellTickets {    void sell();}public class TrainStation implements SellTickets {    public void sell() {        System.out.println("火车站卖票");    }}public class ProxyPoint implements SellTickets {    private TrainStation station = new TrainStation();    public void sell() {        System.out.println("代理点收取一些服务费用...");        station.sell();    }}public class Client {    public static void main(String[] args) {        ProxyPoint proxyPoint = new ProxyPoint();        proxyPoint.sell();    }}

动态代理

动态代理的特点是代理类在运行时动态生成。Java提供了一个代理类Proxy(JDK1.3提供),用于创建代理对象。Proxy.newProxyInstance方法用于获取代理对象:

public static Object newProxyInstance(ClassLoader loader, Class
[] interfaces, InvocationHandler h) { return Proxy.newProxyInstance(loader, interfaces, h);}

InvocationHandler接口的invoke方法参数说明:

  • proxy:代理对象
  • method:对应于在代理对象上调用的接口方法的Method实例
  • args:代理对象调用接口方法时传递的实际参数

实例说明:

public class ProxyFactory {    private TrainStation station = new TrainStation();    public SellTickets getProxyObject() {        SellTickets sellTickets = (SellTickets) Proxy.newProxyInstance(            station.getClass().getClassLoader(),            station.getClass().getInterfaces(),            new InvocationHandler() {                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                    System.out.println("(jdk动态代理)代售点收取了一定的手续费用...");                    Object result = method.invoke(station, args);                    return result;                }            }        );        return sellTickets;    }}public class Client {    public static void main(String[] args) {        ProxyFactory factory = new ProxyFactory();        SellTickets proxyObject = factory.getProxyObject();        proxyObject.sell();    }}

CGLib动态代理

CGLib是第三方开源库,用于动态代理。它通过生成字节码实现动态代理的效果。在没有接口的情况下,CGLib更适合实现动态代理。它的优点是速度快,但缺点是只能代理非final类。

实例说明:

public class TrainStation {    public void sell() {        System.out.println("火车站卖票");    }}public class ProxyFactory implements MethodInterceptor {    private TrainStation station = new TrainStation();    public TrainStation getProxyObject() {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(station.getClass());        enhancer.setCallback(this);        TrainStation obj = (TrainStation) enhancer.create();        return obj;    }    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("代理点收取一些服务费用(CGLib动态代理方式)...");        return methodProxy.invokeSuper(o, objects);    }}public class Client {    public static void main(String[] args) {        ProxyFactory proxyFactory = new ProxyFactory();        TrainStation proxyObject = proxyFactory.getProxyObject();        proxyObject.sell();    }}

对比

  • JDK代理和CGLib代理:在调用次数较少的情况下,JDK代理效率更高。CGLib在JDK1.6及以上版本效率较低,但在大量调用时表现更好。
  • 动态代理与静态代理:动态代理更灵活,适合接口多变的情况。

优缺点

  • 优点:降低耦合度,保护目标对象,扩展功能。
  • 缺点:增加系统复杂度。

代理与装饰者模式

两者的区别主要在于目的和获取方式:

  • 装饰者:用于增强目标对象功能。
  • 静态代理:用于保护和隐藏目标对象。

应用实例

  • Mybatis:通过MapperProxyFactory实现动态代理。
  • Spring AOP:用于实现AOP编程。

转载地址:http://yhzg.baihongyu.com/

你可能感兴趣的文章
python系列【仅供参考】:python 远程rdp
查看>>
python基础
查看>>
Python基本语法与变量类型
查看>>
python基本数据类型(容器)- tuple list dict set
查看>>
python基本工资的调整方案_Python薪资又涨了!这可咋办!
查看>>
Python基准测试和性能分析内存管理和垃圾回收
查看>>
Python基于RESTful风格的接口自动化测试实战
查看>>
python基于pygame实现跨年烟花效果
查看>>
python基于flask搭建http服务(四)—— Docker容器化部署
查看>>
python基于flask搭建http服务(二)—— 实现Excel上传、数据清洗、入库
查看>>
python基于flask搭建http服务(三)—— 使用gunicorn部署项目
查看>>
python基于flask搭建http服务(一)—— 实现数据查询和Excel导出
查看>>
Python块键盘/鼠标输入
查看>>
Python在正确的时区获取当前时间
查看>>
python在心理学研究中的应用有哪些_心理学在线研究可用平台简介和应用进展
查看>>
python系列【仅供参考】:python tornado 集成redis消息订阅的异步任务之后tornado主程序无法启动,解决方案
查看>>
Python在列表理解中使用枚举
查看>>
python在使用HTMLTestRunner时,报告为空,错误提示<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf_8'>...
查看>>
python在gpu上运行_【python】python开启GPU加速
查看>>
Python在def函数中使用for循环
查看>>