专栏首页Java爬坑系列【Java入门提高篇】Day10 Java代理——静态代理

【Java入门提高篇】Day10 Java代理——静态代理

  今天要介绍的是一个Java中一个很重要的概念——代理。

  什么是代理?联系生活想想看,代理似乎并不陌生,最形象的代表便是经纪人,明星一般都有经纪人,经纪人作为中间人,负责代理明星的相关事宜,比如说,有人要请明星去唱歌表演,一般不会直接跟明星联系,而是联系他的经纪人,他的经纪人来负责安排行程,而真正唱歌表演的还是明星本人,经纪人仅仅作为一个附加物存在。

  在Java中,代理也是这样的概念,来看个栗子:

  先来创建一个明星类Stars:

public class Stars implements IStars{
    private String name;

    public Stars(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void sing(){
        System.out.println(getName() + " 唱了一首歌.");
    }

    public void dance(){
        System.out.println(getName() + " 跳了一支舞.");
    }
}

  这是相应的接口:

public interface IStars {
    void sing();
    void dance();
}

  现在创建一个代理类:

public class StarsProxy implements IStars{
    //保存接收的代理对象
    private IStars stars;

    public StarsProxy(IStars stars){
        this.stars = stars;
    }

    @Override
    public void sing() {
        System.out.println("我是代理,我收到了唱歌请求。");
        stars.sing();
        System.out.println("唱歌完毕");
    }

    @Override
    public void dance() {
        System.out.println("我是代理,我收到了跳舞请求。");
        stars.dance();
        System.out.println("跳舞完毕");
    }
}

  来测试一下:

public class Test {
    public static void main(String[] args){
        //创建目标对象
        IStars stars = new Stars("Frank");//代理对象,把目标传给代理对象,建立关系
        IStars starsProxy = new StarsProxy(stars);
        starsProxy.sing();
        starsProxy.dance();
    }
}

  运行结果:

我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了跳舞请求。
Frank 跳了一支舞.
跳舞完毕

  我们可以看到,实际上代理类只是保存了Stars类的一个实例,因为实现的是相同的接口,StarsProxy类必须实现需要代理的Stars类的方法,比如这里的dance和sing,而这个接口正是链接两者的关键,因为实现接口就代表必定存在接口中声明的方法。

  那么,为什么要使用代理呢?

  其实主要目的是为了扩展原有类的功能,想想看,如果那个Stars类不是你写的,而是别人写的,现在要将原有的sing或者dance方法进行改造,比如需要统计唱歌和跳舞的次数,次数大于10则不进行该操作直接返回,这时候用代理就很好实现了,来把代理类稍作修改:

public class StarsProxy implements IStars{
    //保存接收的代理对象
    private IStars stars;
    //保存sing和dance的次数
    private int num;

    public StarsProxy(IStars stars){
        this.stars = stars;
    }

    @Override
    public void sing() {
        if (!ifWork()) {
            return;
        }
        System.out.println("我是代理,我收到了唱歌请求。");
        stars.sing();
        System.out.println("唱歌完毕");
    }

    @Override
    public void dance() {
        if (!ifWork()) {
            return;
        }
        System.out.println("我是代理,我收到了跳舞请求。");
        stars.dance();
        System.out.println("跳舞完毕");
    }

    /**
     * 是否继续工作
     * @return 是返回true,否则返回false
     */
    private boolean ifWork(){
        if (num > 3){
            System.out.println("明星今天已经很累了,明天再来吧。");
            return false;
        }else {
            num++;
            return true;
        }
    }
}

  修改一下测试类:

public class Test {
    public static void main(String[] args){
        //创建目标对象
        Stars stars = new Stars();
        stars.setName("Frank");

        //代理对象,把目标传给代理对象,建立关系
        StarsProxy starsProxy = new StarsProxy(stars);
        for (int i = 0;i < 5; i++){
            starsProxy.sing();
        }
    }
}

  测试结果如下:

我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
我是代理,我收到了唱歌请求。
Frank 唱了一首歌.
唱歌完毕
明星今天已经很累了,明天再来吧。

  看,简单粗暴。

  但其实并没有多少干货,这里仅仅是一种代理的思想,用这种思想可以比较方便的在不直接修改原有类的前提下对原有类的方法进行扩展。为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。可以使业务类只关注业务逻辑本身,保证了业务类的重用性,这也是代理的共有优点。

  但是限制也显而易见:

  1.代理类需要跟被代理类实现相同的接口,这样才能一起向上转型后实现多态。

  2.当被代理的类需要进行的扩展增多时,管理会变得更加困难,之后对被代理类的修改,需要同时修改代理类,增加了修改成本。

  所以不要为了使用而使用,应用在合适的场景才能发挥它真正的作用。

  至此,本篇讲解完毕,欢迎大家继续关注!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Java入门提高篇】Day12 Java代理——Cglib动态代理

      今天来介绍另一种更为强大的代理——Cglib动态代理。   什么是Cglib动态代理?   我们先回顾一下上一篇的jdk动态代理,jdk动态代理是通过接口来...

    弗兰克的猫
  • 【Java入门提高篇】Day26 Java容器类详解(八)HashSet源码分析

      前面花了好几篇的篇幅把HashMap里里外外说了个遍,大家可能对于源码分析篇已经讳莫如深了。

    弗兰克的猫
  • 【Java入门提高篇】Day6 Java内部类——成员内部类

      内部类是什么,简单来说,就是定义在类内部的类(一本正经的说着废话)。   一个正经的内部类是长这样的: public class Outer { c...

    弗兰克的猫
  • 初学java之try-catch-finally语句的实例

    1 /* 2 try - catch语句的例子,模拟向货船上装载集装箱 3 ,如果货船超重,那么货船认为这是一个异常,将拒绝装载集装箱, 4...

    Gxjun
  • JavaSE学习总结(五)——封装,继承,多态很简单

    java面向对象的三大特性是:封装、继承与多态,是面向对象编程的核心。 一、封装 简单说封装就是将同一类事物的特性与功能包装在一起,对外暴露调用的接口。 封装:...

    张果
  • 《你必须知道的.NET》读书笔记一:小OO有大智慧

    此篇已收录至《你必须知道的.Net》读书笔记目录贴,点击访问该目录可以获取更多内容。

    Edison Zhou
  • 常用的设计模式汇总,超详细!

    简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它...

    Java高级攻城狮
  • 常用的设计模式汇总,超详细!

    来源:cnblogs.com/ILoke-Yang/p/8054466.html

    好好学java
  • 来自 BAT 大牛总结的常用设计模式汇总

    原文链接:https://cnblogs.com/chenshuyong/p/9998164.html

    业余草
  • 常用的设计模式汇总,超详细!

    简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它...

    java思维导图

扫码关注云+社区

领取腾讯云代金券