设计模式之代理模式(静态代理&动态代理)

这篇具有很好参考价值的文章主要介绍了设计模式之代理模式(静态代理&动态代理)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、什么是代理模式

2、代理模式的结构

3、代理模式的实现

3.1 静态代理和动态代理概念

3.2 静态代理

3.3 动态搭理

3.3.1 代码实现

3.3.2 Proxy类讲解

4、动态代理VS静态代理

5、代理模式优缺点


1、什么是代理模式

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

2、代理模式的结构

代理(Proxy)模式分为三种角色:

  • 抽象主题(Subject)类: 通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  • 真实主题(Real Subject)类: 实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • 代理(Proxy)类 : 提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

3、代理模式的实现

3.1 静态代理和动态代理概念

Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译期就生成,而动态代理代理类则是在Java运行时动态生成。动态代理又有JDK代理和CGLib代理两种。

(本文中的动态代理主要讲解的是JDK代理,如果大家对CGLib代理感兴趣的话可以自行查阅网上的文章) 

3.2 静态代理

我们直接通过案例来感受一下动态代理,以下是场景描述:

一般明星(对象本身)都会有一个经纪人(代理对象)来帮他处理一些事情,比如明星开演唱会之前收门票费用,预约场地,演唱会结束之后调查观众对该演唱会的反馈之类的事情肯定不能交给大明星做吧,所以这些事情一般都是交给经纪人去处理。

这个例子就是一个典型的代理例子,因此我们来看看通过静态代理如何实现:

明星类(抽象主题类):

public interface bigStar {//抽象主题类
    String Sing();
    void Dance();
}

坤坤类(真实主题类):

public class KunKun implements bigStar{ //真实主题类
    public String Sing(){
        System.out.println("大明星:坤坤开始唱歌");
        return "鸡你太美"; //返回歌词
    }
    public void Dance(){
        System.out.println("大明星:坤坤开始跳舞");
    }
}

 经纪人类(代理类):

public class StaticProxy implements bigStar{ //代理类
    private bigStar star;
    public StaticProxy(bigStar bigStar){
        star=bigStar;
    }

    @Override
    public String Sing() {
        System.out.println("唱歌前收取门票费用、预约场地");
        String sing = star.Sing();
        System.out.println("唱歌结束后帮忙调查观众反馈");
        return sing;
    }

    @Override
    public void Dance() {
        System.out.println("跳舞前收取门票费用、预约场地");
        star.Dance();
        System.out.println("跳舞结束后帮忙调查观众反馈");
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        KunKun kunKun = new KunKun();
        StaticProxy proxy = new StaticProxy(kunKun);
        proxy.Dance();
        System.out.println("------");
        String sing = proxy.Sing();
        System.out.println("歌词为:"+sing);
    }
}

运行结果如下:

设计模式之代理模式(静态代理&动态代理)

可见,我们通过“静态代理”的方式实现了“代理模式”,成功在“坤坤”唱歌、跳舞前做好了准备工作以及在结束后做好了调查观众反馈的工作。这些都是代理类来完成的,看到这里大家肯定意识到了代理模式的一个好处就是:“在被代理对象方法执行前后能做一定的处理、加强”。

但是上述静态代理模式有没有缺点呢?

有!而且很明显!那就是:“杂!乱!如果接口增加一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。”

因此,我们引出另一种实现代理模式的方法:“动态代理”。

3.3 动态搭理

3.3.1 代码实现

动态代理的JDK代理实现主要是通过“Proxy类”来实现的,我们直接来看代码实现,大家耐心看,代码里面有很详细的注释。看不懂可以先看底下对于里面参数的讲解部分。

大明星类(抽象主题类):

public interface bigStar { //大明星类(抽象主题类)
    public String Sing();
    public void Dance();
}

坤坤类(真实主题类):

public class KUN implements bigStar { //坤坤类(真实主题类)
    @Override
    public String Sing() {
        System.out.println("坤坤在唱歌......");
        //返回歌词
        return "鸡你太美";
    }

    @Override
    public void Dance() {
        System.out.println("坤坤在跳舞");
    }
}

经纪人(代理类):

public class StarProxyFactory { //经纪人(代理类)
    public static bigStar getProxy(bigStar star){
        bigStar result=(bigStar)Proxy.newProxyInstance(   //newProxyInstance()方法即返回代理对象
//                newProxyInstance()方法参数说明:
//                ClassLoader loader : 类加载器,用于加载代理类,使用真实对象的类加载器即可
//                Class<?>[] interfaces : 真实对象所实现的接口,代理模式真实对象和代理对象实现相同的接口
//                InvocationHandler h : 代理对象的调用处理程序
                star.getClass().getClassLoader(),
                star.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
//                    InvocationHandler中invoke方法参数说明:
//                    proxy:代理对象
//                    method:对应于在代理对象上调用的接口方法的 Method 实例,比如我们调用了“Sing()”这个方法,那么对应的就是“Sing()”的Method实例
//                    args:对应我们方法传入的参数
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("场地布置、收取门票费用");
                        Object invoke = method.invoke(star, args);
                        System.out.println("场地打扫");
                        return invoke; //返回方法调用结果
                    }
                }
        );
        return result;
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        KUN kun = new KUN();
        bigStar proxy = StarProxyFactory.getProxy(kun);//获取动态代理对象
        //验证是否被代理
        proxy.Dance();
        System.out.println("--------------");
        String sing = proxy.Sing();
        System.out.println("歌词为:"+sing);
    }
}

运行结果如下:

设计模式之代理模式(静态代理&动态代理)

可见,我们通过Java提供的“Proxy类”也实现了代理的效果,但是大家看完可能会一脸懵逼,发生了什么?我在哪?我是谁?

因此接下来我们对“Proxy类”这个类做一个详细的解释。

3.3.2 Proxy类讲解

首先,我们刚刚是通过Proxy.newProxyInstance()来获取一个代理对象,它所需要的参数如下:

设计模式之代理模式(静态代理&动态代理)

可见,我们如果使用Proxy.newProxyInstance()的话,需要对它传入以下参数:

①参数一:指类加载器,意思是需要我们告诉它我们需要用哪个类加载器去加载代理对象,通常我们代理对象与被代理对象可以使用同一个类加载器,因此比如上文我们是代理star对象,因此我们传入的类加载器就是:“star.getClass().getClassLoader()”。

②参数二:指真实对象所实现的接口,代理模式真实对象和代理对象实现相同的接口,因此我们也直接传入真实对象的接口即可:“star.getClass().getInterfaces()”。

③参数三:指代理对象最终调用的程序,一般代理对象调用某个方法后,都会走我们参数三写的这个方法,大家往回看代码会发现我们参数三传入了一个匿名内部类对象“new InvocationHandler()”

大家又可以发现,这个“InvocationHandler类”创建对象时,要求重写里面的invoke方法:

设计模式之代理模式(静态代理&动态代理)

 我们再来逐一说说这几个参数的作用:

  • proxy:代理对象本身
  • method:对应于在代理对象上调用的接口方法的 Method 实例,比如我们调用了“Sing()”这个方法,那么对应的就是“Sing()”的Method实例
  • args:对应我们方法传入的参数

因此呢,我们可以在invoke方法里面做一些方法加强(比如我们之前的代码),也就是我们的“代理”。

以上便是动态代理实现代理模式的代码。

4、动态代理VS静态代理

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
如果接口增加一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题

5、代理模式优缺点

优点:

  •  代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用。
  • 代理对象可以扩展目标对象的功能。
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度。

缺点:

  • 增加了系统的复杂度。

以上是代理模式的详解,大家麻烦点个赞和关注可以嘛!现在点关注就是老粉啦!文章来源地址https://www.toymoban.com/news/detail-435566.html

到了这里,关于设计模式之代理模式(静态代理&动态代理)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式的使用——模板方法模式+动态代理模式

    一、需求介绍   现有自己写的的一套审批流程逻辑,由于代码重构,需要把以前的很多业务加上审批的功能,再执行完审批与原有业务之后,生成一个任务,然后再统一处理一个任务(本来是通过数据库作业去处理的,后来说这个任务要马上去处理,只能去统一添加一个处

    2024年02月10日
    浏览(35)
  • 代理模式--静态代理和动态代理

    定义:代理模式就是代替对象具备真实对象的功能,并代替真实对象完成相应的操作并且在不改变真实对象源代码的情况下扩展其功能,在某些情况下,⼀个对象不适合或者不能直接引⽤另⼀个对象,⽽代理对象可以在客户端和⽬标对象之间起到中介的作⽤ 使用代理模式可以

    2024年02月15日
    浏览(38)
  • Java代理模式——静态代理与动态代理

    代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。 可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被

    2024年02月13日
    浏览(45)
  • 代理模式:静态代理+JDK/CGLIB 动态代理

    代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。 代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法

    2024年02月13日
    浏览(35)
  • 温故知新之:代理模式,静态代理和动态代理(JDK动态代理)

    代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。 静态代理 是一种代理模式的实现方式,它在编译期间就已经确定了代理对象,需要为每一个被代理对象创建一个代理类。静态代理的实现比较简单,但是每个被代理对象都需要创建

    2024年02月11日
    浏览(47)
  • 代理模式【静态代理和动态代理实现业务功能扩展】

    我们在不修改业务的情况下想要给它增加一些功能,这就需要使用代理模式。 我们不会在原有业务上直接修改,为了避免修改导致程序不可逆转的破坏。 三种角色:抽象角色-接口、真实角色-实现类和代理角色-代理类。 真实角色和代理角色继承的是同一个抽象角色接口!

    2024年02月16日
    浏览(32)
  • Java 代理模式详解,静态代理与动态代理的区别及优缺点

    代理模式是一种常用的设计模式,它允许通过引入一个代理对象来控制对目标对象的访问。在Java中,代理模式被广泛应用,它可以提供额外的功能,如权限检查、缓存、日志记录等,同时还能在不修改目标对象的情况下对其进行扩展。 代理模式(Proxy Pattern)是指通过代理对象

    2024年02月11日
    浏览(43)
  • Java设计模式 (三) 代理设计模式

    什么是代理设计模式? 代理设计模式是一种结构型设计模式,它允许创建一个代理对象,用于控制对其他对象的访问。代理模式通常用于在访问对象时添加一些附加操作,而不是直接访问真实对象。代理模式可以在不改变原始类代码的情况下,通过引入代理类来增强功能。 代

    2024年02月12日
    浏览(41)
  • 设计模式|代理模式

    ​代理模式指为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象若不能直接引用另一个对象,而代理对象可以在客户端与目标对象之间起到中介的作用。 普通代理 普通代理模式是指在代理模式中,代理对象和真实对象都实现了相同的接口或继承

    2024年02月04日
    浏览(31)
  • 设计模式--代理模式

    笔记来源:尚硅谷Java设计模式(图解+框架源码剖析) 1)代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即 通过代理对象访问目标对象 2)这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能 3)被代理的对象可以

    2024年02月10日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包