Java 代理

代理模式的核心作用就是通过代理,控制对对象的访问。这跟实际中是一样的,比如说明星都有经纪人,这就是一个代理,比如有人要找某明星拍戏,那么首先处理这事的是他的经纪人,虽然拍戏需要自己拍,但是拍戏前后的一些必须要做的事等等,都由这个经纪人来处理。
  在程序中也是如此,通过代理,可以详细控制访问某个或者某类对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。这也是AOP的实现原理。
  那么代理模式的核心角色该如何设计呢?

设计思路:定义一个抽象角色,让代理角色和真实角色分别去实现它。
1. 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用它只关注真正的业务逻辑,比如拍戏。
2. 代理角色:实现抽象角色,是真实角色的代理,通过真是角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作,比如谈合同,布置场地等等。

  下面来具体实现这个代理模式,代理模式分为静态代理和动态代理。静态代理是我们自己创建一个代理类,而动态代理是程序自动帮我们生成一个代理,我们就不用管了。

1. 静态代理

根据上面的实现步骤,首先来写一个抽象角色:

<span style="color:#000000"><code class="language-java"><span style="color:#880000">/**
 *<span style="color:#4f4f4f"> @Description</span> 接口类
 *<span style="color:#4f4f4f"> @author</span> Ni Shengwu
 *
 */</span>
<span style="color:#000088">public</span> <span style="color:#000088">interface</span> <span style="color:#4f4f4f">Star</span> {

    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">confer</span>(); <span style="color:#880000">//面谈</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">sing</span>(); <span style="color:#880000">//唱歌</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">collectMoney</span>(); <span style="color:#880000">//收钱</span>
}</code></span>
  •  

这个抽象类中有三个方法,现在分别让真实角色和代理角色来实现该抽象类:

<span style="color:#000000"><code class="language-java"><span style="color:#880000">/**
 *<span style="color:#4f4f4f"> @Description</span> 真实对象
 *<span style="color:#4f4f4f"> @author</span> Ni Shengwu
 *
 */</span>
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">RealStar</span> <span style="color:#000088">implements</span> <span style="color:#4f4f4f">Star</span> {

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">confer</span>() {
        System.out.println(<span style="color:#009900">"RealStar.confer()"</span>);
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">sing</span>() {
        System.out.println(<span style="color:#009900">"RealStar(周杰伦).sing()"</span>);
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">collectMoney</span>() {
        System.out.println(<span style="color:#009900">"RealStar.collectMoney()"</span>);
    }

}</code></span>
  •  

唱歌部分,注明一下周杰伦,等会好区分。下面再来看下代理类。

<span style="color:#000000"><code class="language-java"><span style="color:#880000">/**
 *<span style="color:#4f4f4f"> @Description</span> 代理类
 *<span style="color:#4f4f4f"> @author</span> Ni Shengwu
 *
 */</span>
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">ProxyStar</span> <span style="color:#000088">implements</span> <span style="color:#4f4f4f">Star</span> {

    <span style="color:#000088">private</span> Star star;

    <span style="color:#000088">public</span> <span style="color:#009900">ProxyStar</span>(Star star) { <span style="color:#880000">//到时候传进来真实的star</span>
        <span style="color:#000088">super</span>();
        <span style="color:#000088">this</span>.star = star;
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">confer</span>() {
        System.out.println(<span style="color:#009900">"ProxyStar.confer()"</span>);
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">sing</span>() {
        <span style="color:#880000">//其他事都能干,唯一不能干的就是唱歌,唱歌还是得要周杰伦本人来唱</span>
        star.sing(); <span style="color:#880000">//让他本人来唱</span>
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">collectMoney</span>() {
        System.out.println(<span style="color:#009900">"ProxyStar.collectMoney()"</span>);
    }

}</code></span>
  •  

  在代理类中,可以看到,维护了一个Star对象,通过构造方法传进来一个真实的Star对象给其赋值,然后在唱歌这个方法里,使用真实对象来唱歌。所以说面谈、收钱都是由代理对象来实现的,唱歌是代理对象让真实对象来做。
下面写个客户端的测试用例:

<span style="color:#000000"><code class="language-java"><span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">Client</span> {

    <span style="color:#000088">public</span> <span style="color:#000088">static</span> <span style="color:#000088">void</span> <span style="color:#009900">main</span>(String[] args) {
        Star real = <span style="color:#000088">new</span> RealStar();
        Star proxy = <span style="color:#000088">new</span> ProxyStar(real);

        proxy.confer();
        proxy.sing();
        proxy.collectMoney();
    }

}</code></span>
  •  

输出结果:

ProxyStar.confer()
RealStar(周杰伦).sing()
ProxyStar.collectMoney()

可以看出,客户端只跟代理对象打交道,代理对象把能做的都做了,比如面谈和收钱,唱歌呢,是调用真实对象去唱。

2. 动态代理

  动态代理比静态代理使用的更广泛,动态代理在本质上,代理类不用我们来管,我们完全交给工具去生成代理类。Star接口和RealStar实现类还是和上面的一样,下面来定义一下代理类,使用动态代理需要实现InvocationHandler接口,并覆写里面的invoke方法,如下:

 

  可以看出,思路和静态代理是一样的,先通过构造方法把真正的对象传进来,然后执行代理的部分是invoke方法中,在该方法中,我们进行一次判断,只有当需要唱歌的时候,我就调用刚刚传进来的真实对象来唱,其他事情由代理代替真实对象来做,这里只用控制台输出来模拟一下。
  最后来写个客户端测试一下:

<span style="color:#000000"><code class="language-java"><span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">Client</span> {

    <span style="color:#000088">public</span> <span style="color:#000088">static</span> <span style="color:#000088">void</span> <span style="color:#009900">main</span>(String[] args) {

        Star realStar = <span style="color:#000088">new</span> RealStar();
        StarHandler handler = <span style="color:#000088">new</span> StarHandler(realStar);

        <span style="color:#880000">//创建代理类</span>
        Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), <span style="color:#000088">new</span> Class[]{Star.class}, handler);       

        proxy.sing();
    }

}</code></span>
  •  

看下控制台输出:

面谈
RealStar(周杰伦).sing()
收钱

  由此可见,使用代理可以在执行某个逻辑的前后加上新的逻辑,这是很好的功能,实际中Spring的AOP用的就是这种技术。

基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip 个人大四的毕业设计、课程设计、作业、经导师指导并认可通过的高分设计项目,评审平均分达96.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 [资源说明] 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设或者课设、作业,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96.5分,放心下载使用! 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),供学习参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值