当前位置:首页 > CN2资讯 > 正文内容

设计模式之代理模式 静态代理和动态代理

13小时前CN2资讯


​​welcome to my blog​​

代理模式的定义

《大话设计模式》中对于代理模式的描述: 代理模式为其他对象提供一种代理以控制对这个对象的访问.
通俗点说就是, 通过一个中间对象访问目标对象.

代理模式在生活中的体现

租房时需要看房, 往往是中介的人带着咱们去看房, 并不是直接由房东带着去看房. 注意到房子是属于房东的属性, 但是我们并没有通过房东访问这个属性, 而是通过中介访问这个属性, 这种看房子的方式就体现了代理模式的思想

代理模式的分类

根据代理类出现的时机, 可以将代理模式分成静态代理和动态代理
静态代理: 程序执行前代理类便已经存在,也就是说程序执行前便存在代理类对应的class文件
动态代理: 程序执行中使用反射机制生成代理类

静态代理

三个关键:

  • 目标类和代理类的抽象接口
  • 目标类
  • 静态代理类
  • 使用静态代理的三个步骤:

  • 创建目标对象
  • 创建静态代理对象
  • 使用静态代理对象调用目标对象的方法
  • //Subject是目标类和代理类的接口
    interface Subject{
    void doSomething();
    }

    //RealSubject表示目标类
    class RealSubject implements Subject{
    @Override
    public void doSomething() {
    System.out.println("向租客展示房子...");
    }
    }

    //Proxy表示代理类
    class Proxy implements Subject{
    //代理类中需要有目标类的引用, 这样才能通过代理对象调用目标对象的方法
    //这里使用接口类型, 体现了"依赖倒转"原则, 也就是面向接口编程;

    Subject target;
    Proxy(Subject target){
    this.target = target;
    }
    @Override
    public void doSomething() {
    //在调用目标对象方法之前可以执行一些其他操作
    System.out.println("调用目标对象方法之前可以执行一些其他操作");
    //调用目标对象的方法
    target.doSomething();
    //在调用目标对象方法之后可以执行一些其他操作
    System.out.println("调用目标对象方法之后可以执行一些其他操作");
    }
    }
    public class StaticProxyDemo {
    public static void main(String[] args) {
    //使用代理模式, 如下三步
    //1.创建目标对象
    Subject subject = new RealSubject();
    //2.创建代理对象, 并将目标对象传给代理对象
    //创建Proxy对象时, 向构造函数中传入的是RealSubject实例, 并不是Subject,
    //体现了"里式替换"原则, 也就是把父类替换成子类, 程序的行为没有变化
    Subject proxy = new Proxy(subject);
    //3.通过代理对象调用目标对象的方法
    proxy.doSomething();
    }
    }

    静态代理优缺点

    优点:
    实现了客户端和目标对象之间解耦和

    缺点:
    代理类需要实现接口中的所有方法, 如果接口中的方法改变了, 那么既需要修改目标类, 也需要修改代理类

    动态代理

    动态代理不需要程序执行前就存在代理类的class文件, 而是在程序执行中直接生成代理对象, 并且不需要实现接口中的所有方法.
    动态代理有两种实现方式:
    JDK动态代理:
    Java提供的动态代理技术, 可以在运行时创建接口的代理实例
    目标类必须存在接口

    CGLib动态代理:
    采用底层的字节码技术, 在运行时创建子类代理实例
    目标类存在接口或者不存在接口都可以

    JDK动态代理

    三个关键:

  • 目标类的抽象接口
  • 目标类
  • 动态代理类
  • 使用JDK动态代理的三个步骤:

  • 创建目标对象
  • 创建动态代理对象
  • 使用动态代理对象调用目标对象的方法
  • 两个核心:

  • 定义动态代理类时需要实现InvocationHandler接口
  • 创建动态代理对象时需要使用Proxy类
  • import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;

    //Subject是目标类和代理类的接口
    interface Subject{
    void doSomething();
    }

    //RealSubject表示目标类
    class RealSubject implements Subject{
    @Override
    public void doSomething() {
    System.out.println("向租客展示房子...");
    }
    }

    //DynamicSubject表示动态代理类; 可以发现并不需要实现Subject接口
    //之后会使用代理对象调用目标对象的方法
    class DynamicSubject implements InvocationHandler {
    //代理类中需要有目标类的引用, 这样才能通过代理对象调用目标对象的方法
    Subject subject;
    DynamicSubject(Subject subject){
    this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //在调用目标对象方法之前可以执行一些其他操作
    System.out.println("调用目标对象方法之前可以执行一些其他操作");
    //调用目标对象的方法; subject是目标对象; args是目标对象的method方法的参数
    method.invoke(subject, args); //不需要具体指明调用目标对象的哪个方法
    //在调用目标对象方法之后可以执行一些其他操作
    System.out.println("调用目标对象方法之后可以执行一些其他操作");
    return null;
    }
    }

    public class JDKProxyDemo {
    public static void main(String[] args) {
    //使用代理模式, 如下三步
    //1.创建目标对象
    Subject subject = new RealSubject();
    //2.创建动态代理对象proxy, 但是不能通过这个对象调用目标对象的方法,
    InvocationHandler proxy = new DynamicSubject(subject);
    //使用Proxy类将动态代理对象和目标对象联系起来, 生成真正的动态代理对象
    //newProxyInstance()需要传入三个参数:加载目标类的类加载器,目标类实现的接口, 动态代理对象proxy
    //newProxyInstance()返回的是Object类型, 需要强转成Subject类型
    Subject dynamicProxy = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), proxy);
    //3.使用Proxy类创建动态代理类
    dynamicProxy.doSomething();
    }
    }

    JDK动态代理的特点

    动态代理类的invoke方法中, 不需要具体指明调用目标对象的哪个方法
    目标类必须存在接口, 对应到上面的例子就是RealSubject类实现了Subject的接口, 没有接口就不能使用JDK动态代理

    CGLib动态代理

    CGLib可以为没有实现接口的目标类创建代理
    为目标类动态生成一个子类, 在子类中重写目标类的所有非final方法(因为final方法不能被子类继承). 最重要的是在子类中采用方法拦截技术, 拦截所有对父类方法的调用, 顺势织入横切逻辑


      你可能想看:

      扫描二维码推送至手机访问。

      版权声明:本文由皇冠云发布,如需转载请注明出处。

      本文链接:https://www.idchg.com/info/23973.html

      分享给朋友:

      “设计模式之代理模式 静态代理和动态代理” 的相关文章

      搬瓦工(BandwagonHost)VPS指南:选择适合你的方案与实用技巧

      搬瓦工(BandwagonHost)是一家在VPS领域颇具声望的提供商。作为杭州的一家企业,搬瓦工致力于为用户提供高性价比的虚拟专用服务器服务,在业内吸引了大量的关注和客户。 说到搬瓦工的优势,机房和线路的多样性是一个重要因素。它在多个国家设有数据中心,包括香港、美国和日本等地。这种广泛的选择使用户...

      ZGOVPS优惠码使用指南:如何享受高性能VPS服务的优惠

      ZGOVPS是一家在VPS服务领域备受瞩目的品牌。作为一个提供高性能虚拟专用服务器的商家,它在业内以性价比高、网络稳定和良好口碑而受到广泛欢迎。我在使用ZGOVPS的过程中,深刻感受到了它对客户需求的敏锐把握和优质服务的承诺。 从公司的背景来看,ZGOVPS专注于为全球用户提供专业的VPS解决方案,...

      甲骨文云免费申请详解:轻松获取免费云服务

      甲骨文云免费申请概述 当提到云服务的时候,甲骨文云绝对是一个值得关注的选项。甲骨文云(Oracle Cloud)是一项提供强大基础设施和服务的云计算平台,尤其在数据管理、分析和应用开发方面具有突出的优势。在这个日益数字化的时代,免费试用计划让用户能够亲自体验甲骨文云的强大功能,激起了很多人的好奇和兴...

      续费同价服务器:云服务的透明定价策略与用户优势

      续费同价服务器是什么呢?说白了,就是云服务提供商在定价上采取的一种政策。无论是新用户第一次购买,还是老用户续费,价格都是一样的。这种做法让很多用户感到安心,不用担心下次续费时价格会大幅上涨。这一策略在云服务行业越来越受到重视,也给用户带来了不少好处。 首先,续费同价服务器让价格变得透明。我之前在选择...

      使用宝塔面板配置与优化IPv6技术的全面指南

      宝塔面板简介 宝塔面板是一款非常实用的服务器管理工具,它的功能覆盖了许多方面。从LAMP、LNMP环境的快速搭建到监控、FTP、数据库及JAVA的管理,宝塔面板都能提供一键式的解决方案。通过这样一款工具,服务器的管理不再复杂,用户只需通过友好的Web界面进行操作,即可轻松实现各种任务。 我常常使用宝...

      掌握域名优惠,轻松获取注册及续费折扣

      什么是域名优惠? 在网络世界中,域名可以说是你的“家”,而域名优惠则是你入住这个“家”时所获取的折扣或者促销活动。简单来说,域名优惠就是在购买或者续费域名时,所享受到的价格减免。这种优惠通常由域名注册商提供,旨在吸引更多用户注册和使用他们的服务。我们可以看到,域名优惠不仅限于初次注册,也包括后期的续...