代理模式

1、什么叫代理模式

官方解释:

(1) 为其他对象提供一种代理。以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

(2) 对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。

(3) 代理模式最主要的就是有一个公共接口,一个具体的类,一个代理类,代理类持有具体类的实例,代为执行具体类实例方法。代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。这里的间接性就是指不直接调用实际对象的方法,那么我们在代理过程中就可以加上一些其他用途。

通俗解释:A要做某件事,但是A临时别其他事情耽搁没时间,B代替A去做这件事。

2、什么叫动态代理,什么叫静态代理

动态代理:代理类在程序运行时创建的代理方式被成为动态代理。

静态代理:程序未运行前,编译阶段就已经创建好的代理类,这种代理为静态代理。

3、静态代理样例

---- 我们以xiaojiang (被代理者)做完作业,xiaozhou(代理者) 作为班长,老师让xiaozhou代交,避免每个学生都要跑一趟浪费学习时间,以此为例写一个简单的静态代理样例

//交作业的接口
public interface Homework  {
    void handHomework ();
}
//xiaojiang需要交作业
public class XiaoJiang implements Homework {
    private String name;

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

    @Override
    public void handHomework() {
        System.out.println(name+"来交作业啦");
    }
}
//xiaozhou 虽然为班长但是也要交作业
public class XiaoZhou implements Homework {
    private XiaoJiang xiaoJiang;

    public XiaoZhou(Homework xiaoJiang) {
        this.xiaoJiang = (XiaoJiang) xiaoJiang;
    }

    @Override
    public void handHomework() {
        xiaoJiang.handHomework();
    }
}
//我们调用xiaozhou交作业的方法
public static void main(String[] args) {
        XiaoJiang xiaoJiang = new XiaoJiang("xiaojiang");
        XiaoZhou xiaoZhou = new XiaoZhou(xiaoJiang);
        xiaoZhou.handHomework();
}

main运行完后控制台输出是:    xiaojiang来交作业啦

注意到没有,我们main方法里,交作业的发起人是xiaozhou 而不是xiaojiang,这就是静态代理。最终是代理者替被代理者执行了某事

那么问题来啦,为什么要这样做呢,这样做有什么好处呢?

为什么要这样做:代理模式的核心作用就是通过代理,控制对对象的访问。

  我再举一个例子:比如说明星都有经纪人,有人要找某明星拍戏,那么首先处理这事的是他的经纪人,虽然拍戏需要自己拍,但是拍戏前后的一些必须要做的事等等,都由这个经纪人来处理。

这样做有什么好处:对象只需要关注自己需要执行的业务,将关注点和系统级任务分开,业务分离。

  就想找明星拍戏一样,明星只需要拍戏就行,至于拍戏前的签合同,拍完戏之后的酬劳领取等,都由经纪人代理。

理解啦没有~~~

 

 

 

笔记最初我们有讲过代理模式分为静态代理和动态代理。上面讲了静态代理。我们再来讲讲动态代理

为什么有了静态代理还会推出动态代理?

我们观察到静态代理确实帮我们实现了基本的业务分离。但是假设xiaojiang同学除了交作业这个事情外,还有其他的事情呢?

public interface Homework  {
    //交作业
    void handHomework ();
    //写作业
    void writeHomework ();
}

 

    @Override
   //交作业的方法
public void handHomework() { beforeMethod(); xiaoJiang.handHomework(); afterMethod(); } private void afterMethod() { System.out.println("事情处理完成"); } private void beforeMethod() { System.out.println("开始处理事情"); }

假设我们需要在xiaojiang每次处理事情前都输出开始和完成,静态代理的话我们是不是得在每个方法前后都得加上beforeMethod 和afterMethod()? 这样是不是很麻烦!!!

我们来看下动态代理是如何实现的~~~~~

4、动态代理样例

在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。

现在我们编写一个类实现InvocationHandler接口,这个接口代理homework接口

public class MyInvocationHandler<T> implements InvocationHandler {
   //代理对象
private T target; public MyInvocationHandler(T target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeMethod(); Object invoke = method.invoke(target, args); afterMethod(); return invoke; } private void afterMethod() { System.out.println("事情处理完成"); } private void beforeMethod() { System.out.println("开始处理事情"); } }

此时我们把beforeMethod()和afterMethod()移入到MyInvocationHandler中。

笔记到现在我们总共编写了四个类,xiaojiang + xiaozhou +homework+MyInvocationHandler。

xiaozhou 作为xiaojiang的静态代理类我们不再使用,现在我们用MyInvocationHandler代理xiaojiang交作业

好啦,编写测试类

    public static void main(String[] args) {
        //创建xiaojiang对象
        XiaoJiang xiaoJiang = new XiaoJiang("xiaojiang");
        //创建xiaojiang的动态代理执行器
        MyInvocationHandler handler = new MyInvocationHandler<Homework>(xiaoJiang);
        //创建xiaojiang的动态代理对象
        Homework homework = (Homework) Proxy.newProxyInstance(Homework.class.getClassLoader(), new Class<?>[]{Homework.class}, handler);
        //代理xiaojiang交作业
        homework.handHomework();
    //代理xiaojiang写作业 homework.writeHomework(); }

这里我们执行查看结果

会发现控制台执行交作业和写作业之前都会打印事情开始和结束,完美避免了我们重复调用的麻烦!!

5、总结

动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。是因为所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以我们只要在invoke方法中统一处理,就可以对所有被代理的方法进行相同的操作了。例如,这里的方法计时,所有的被代理对象执行的方法都会被计时,然而我只做了很少的代码量,动态代理的过程,代理对象和被代理对象的关系不像静态代理那样一目了然,清晰明了。

 

posted @ 2021-02-22 18:37  十二A~  阅读(238)  评论(0)    收藏  举报