了解Java代理(一):静态代理

前言

        从业几年,工作上一直忙于各种业务,自己的时间少了,学习动力一点点耗尽,再加上本身又比较懒散,慢慢就放下钻研了,偶尔心血来潮会翻翻技术相关的书,却发现里面的东西总是一知半解。相信很多人也和我一样困于这个状态,一直如此总不是个办法,想想还是决定写写博客,复习巩固下知识。

        正巧最近想深入了解下持久化框架,大致翻了下书,代理的出现频率挺高,就作为首个需要复习的点吧。

1、阐述代理

1.1、什么是代理?

        引用《Java编程思想》中对代理的解释:代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色。

        如果感觉还是很抽象很模糊,那结合我们的生活就好了。以老师为例,老师要批改作业,但是这之前肯定要收作业,又不想自己去收,怎么办呢?不如选个课代表吧,收作业的事叫课代表干了,老师仅专注于批改作业。如此,课代表就是老师的代理,课代表作为“代理对象”代替了老师这个“实际对象”去收取学生的作业,充当老师和学生的中间人角色,实现最终批改作业的目的。

        从上面的例子我们就能发现,代理有些非常明显的好处:

功能增强:能更方便的对实际对象的功能进行扩展(除了可以让课代表收作业,还可以让其做更多其他事)。

控制访问:有效把控对实际对象的操作和访问(老师如果和一个个去学生那收作业批改作业,就要承受更多的任务和压力,有个课代表作为中间人就不那么累了)。

解耦合:降低代码的耦合度,减少相互依赖(老师只需要专注于批改作业,杂七杂八的事可以直接交给课代表)。

        到此,大家对代理有个大致的理解了,概念并不复杂。

1.2、代理的分类

        根据代理创建的时期区分,我们可将代理分成两大类:静态代理动态代理

        什么是静态代理?什么又是动态代理?

        静态代理就是在代码编译时,就已经确定了代理对象和被代理对象的关系,即我们编写代码的时就已经实际创建了代理对象。

        反之,如果代理对象不是直接在编写代码时创建,而是在我们程序运行期间生成,即是动态代理。在java中,动态代理也分很多种模式,后续主要会拿大家说的比较多的JDK动态代理CGLIB动态代理作为主要示例。

2、静态代理的实现

        接下来就用实际代码来演示静态代理的实现。

        1、首先,创建一个Person接口,包含一个doSomething方法。老师和课代表都是人,都会做事,所以后续的老师类(实际对象)和课代表(代理对象)类都会实现这个接口:

public interface Person {
    void doSomething();
}

        2、创建老师类(实际对象),实际做的事是批改作业:

/**
 * 老师
 */
public class Teacher implements Person {
    @Override
    public void doSomething() {
        System.out.println("老师:批改作业");
    }
}

        3、创建课代表类(代理对象),实际做的事是收作业,交由老师批改,批改完成后发回作业。

/**
 * 课代表
 */
public class Representative implements Person {

    private Person teacher;

    public Representative(Person teacher) {
        this.teacher = teacher;
    }

    @Override
    public void doSomething() {
        System.out.println("课代表:收作业");
        teacher.doSomething();
        System.out.println("课代表:发作业");
    }
}

        4、再来创建一个学生类(请求发起对象)来交作业:

/**
 * 学生
 */
public class Student {

    //交作业
    public void handInHomework(Person person) {
        System.out.println("学生:交作业");
        person.doSomething();
    }
}

        5、先来看看没有代理的情况和结果,学生直接将作业交给老师:

public class StaticTest {
    public static void main(String[] args) {

        //老师
        Person teacher = new Teacher();

        //学生
        Student student = new Student();

        //交作业
        student.handInHomework(teacher);
    }
}
学生:交作业
老师:批改作业

        6、有代理的情况,学生将作业交给课代表:

public class StaticTest {
    public static void main(String[] args) {
        
        //老师
        Person teacher = new Teacher();
        
        //课代表
        Person representative = new Representative(teacher);

        //学生
        Student student = new Student();
        
        //交作业
        student.handInHomework(representative);
    }
}
学生:交作业
课代表:收作业
老师:批改作业
课代表:发作业

        从以上代码可以看到,学生提交作业时,并不需要关心作业具体提交给老师还是课代表,因为老师和课代表共同实现了Person接口,课代表作为学生和老师的中间人,将除了批改作业外的其他事情接管。

总结

        虽然了解类静态代理的实现和作用,但静态代理的弊端也是比较明显的,由于代理对象都是编译时就直接手动创建的,虽然一定程度上也做到了解耦合,但这还远远不够。当对象新增方法,或有需要代理的新类型的实际对象时,就需要对代理对象进行修改甚至编写新的代理,这种做法很不灵活,实用场景也稍少。

        作为一名懒惰的程序员,不想去一个个编写,那怎么办呢?动态代理是很好的替代方案,后续章节我们就继续延伸讲讲动态代理,待续......

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值