博客
关于我
厚积薄发打卡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/

你可能感兴趣的文章
No 'Access-Control-Allow-Origin' header is present on the requested resource.
查看>>
NO 157 去掉禅道访问地址中的zentao
查看>>
no available service ‘default‘ found, please make sure registry config corre seata
查看>>
no connection could be made because the target machine actively refused it.问题解决
查看>>
No Datastore Session bound to thread, and configuration does not allow creation of non-transactional
查看>>
No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
查看>>
No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
查看>>
No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
查看>>
No mapping found for HTTP request with URI [/logout.do] in DispatcherServlet with name 'springmvc'
查看>>
No module named 'crispy_forms'等使用pycharm开发
查看>>
No module named cv2
查看>>
No module named tensorboard.main在安装tensorboardX的时候遇到的问题
查看>>
No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
查看>>
No new migrations found. Your system is up-to-date.
查看>>
No qualifying bean of type XXX found for dependency XXX.
查看>>
No resource identifier found for attribute 'srcCompat' in package的解决办法
查看>>
no session found for current thread
查看>>
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
查看>>
NO.23 ZenTaoPHP目录结构
查看>>
no1
查看>>