关于代理模式粗略理解

    科技2022-07-11  83

    代理模式

    简单来说就是代理对象起到中介的作用

    流程也就是:使用者 - 代理 - 服务者

    用图表示则为:

    好处

    可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.

    因为别人写的代码是可以正常运行的,如果随便修改源代码出现bug了就难顶了~

    因此如果需要修改,可以通过代理的方式来扩展该方法

    静态代理

    静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.

    例子

    我们定义一个接口

    public interface Store { void sale(); }

    然后定义一个实现类

    public class StoreImpl implements Store{ @Override public void sale() { System.out.println("卖东西"); } }

    然后定义代理

    public class StoreProxy implements Store { private Store targetObj; public StoreProxy(Store targetObj) { this.targetObj = targetObj; } @Override public void sale() { System.out.println("前驱代码"); targetObj.sale(); System.out.println("后继代码"); } }

    测试

    public class Test { public static void main(String[] args) { Store store = new StoreImpl(); StoreProxy proxy = new StoreProxy(store); proxy.sale(); } }

    执行结果

    前驱代码 卖东西 后继代码

    综上所述

    一、好处: 可以做到在不修改目标对象的功能前提下,对目标功能扩展.

    二、缺点:

    ①因为代理类需要与实现类实现一样的接口,所以会有很多代理类

    ②一旦接口增加方法,目标对象与代理对象都需要修改

    为了解决这些缺点 我们引入动态代理

    动态代理

    动态代理有以下特点: ①.不需要实现接口 ②.代理对象的生成是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型) ③因此动态代理也叫做:JDK代理,接口代理

    使用的API

    java.lang.reflect.Proxy类的

    /** * * @param loader 指定当前目标对象使用类加载器 * @param interfaces :目标对象实现的接口的类型 * @param h 事件处理,执行目标对象的方法时,会触发事件处理器的方法, * 会把当前执行目标对象的方法作为参数传入。简单来说就是=>如何代理 * @return */ public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){ }

    例子

    接口和实现类跟静态代理是一样的,就不重复写了.

    首先是一个创建代理对象的工厂

    package ProxyDemo.DynamicProxyDemo; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { private StoreImpl targetObj; public ProxyFactory(StoreImpl targetObj) { this.targetObj = targetObj; } public Object createProxyInstance(){ return Proxy.newProxyInstance(targetObj.getClass().getClassLoader() , targetObj.getClass().getInterfaces(), (Object proxy, Method method, Object[] args) -> { System.out.println("前驱代码"); //这里args写不写都行 因为是args里啥都没有 Object obj = method.invoke(targetObj,args); System.out.println("后继代码"); return obj; }); } }

    然后是测试

    public class Test { public static void main(String[] args) { StoreImpl obj = new StoreImpl(); Store proxy = (Store) new ProxyFactory(obj).createProxyInstance(); proxy.sale(); } }

    执行结果

    前驱代码 卖东西 后继代码

    总结

    动态代理不需要实现接口,但是目标(实现类)对象通常要实现接口,否则不能用动态代理。

    目标对象的方法就是让代理对象调用invoke来执行的

    当然我们也可以不写实现类,那么在说明如何代理的时候 也就是传递InvocationHandler h这个参数的时候 说明如何代理即可。换句话说就是把invoke的内容移动到这了而已。

    至于不写实现类的例子…咕咕咕,有缘再更

    Processed: 0.031, SQL: 8