【设计模式】静态代理和动态代理

一、静态代理

什么是代理

比如你要租房子,但是你没有时间去看房子,就把租房子的事情交给了女朋友的闺蜜来处理,然后你女朋友的闺蜜帮你租了一个两室一厅,开始了你们的故事。。。。

比如你想吃蛋炒饭,但是你不喜欢做饭,所以你把女朋友送去了新东方,学了几年厨师,然后你开始了永无休止的蛋炒饭生活。。。

比如你想买自由女神手里的冰激淋,但是她不卖给你,你就把钱给了太上老君,太上老君帮你去买自由女神的冰激淋。。。

总结下来就是你想要结果,但是不想参与过程,那么就可以使用代理模式,将这个具体过程委托给某一个角色,你只关注结果即可。

静态代理演示

先定义一个接口,描述下要做什么事情:

/**
 * @author zhangjian
 * @version 1.0.0
 * @date 2021/11/16
 * @since 1.0.0
 */
public interface Work {
    /**
     * 写代码
     */
    void coding();
}

然后,描述一个真正能够做这个事情的角色:

/**
 * @author zhangjian
 * @version 1.0.0
 * @date 2021/11/16
 * @since 1.0.0
 */
public final class JavaWork implements Work{

    @Override
    public void coding() {
        System.out.println("Java coding.....");
    }

}

然后,描述一个不想干这个事情,但是有能力让别人干的角色:

/**
 * @author zhangjian
 * @version 1.0.0
 * @date 2021/11/16
 * @since 1.0.0
 */
public final class LeaderWork implements Work{

    private  JavaWork javaWork;

    public LeaderWork(JavaWork work){
        this.javaWork = work;
    }

    @Override
    public void coding() {
        javaWork.coding();
    }
}

最后,通过一个简单的示例,看一下具体代理的过程:

public class SimpleStatic {
    public static void main(String[] args) {
        // 这是一个Java程序员
        JavaWork javaWork = new JavaWork();
        // 这是项目经理
        LeaderWork leaderWork = new LeaderWork(javaWork);
        // 公司安排项目经理实现一个Hello world,但是项目经理不会写,把coding的工作安排给了javaWork这个程序员
        leaderWork.coding();
    }
}

到这里,相信静态代理的大概玩法基本已经清晰了。

静态代理的优缺点

知道了静态代理是怎么回事以后,接下来探讨下静态代理为什么叫静态,有什么优劣?

优点一、可以隐藏具体实现细节
优点二、通过代理可以聚合复杂的内部实现
优点三、提高逻辑复用程度

缺点一、高耦合,接口变动会波及所有实现类
缺点二、如果Work这个接口内部抽象方法特别多,代理的行为就会变的越来越重
缺点三、代理内部的关系维护很难实现动态切换,所以叫静态代理

二、动态代理

什么是动态代理

所谓的动态代理,实际上和静态代理大同小异,搞清楚动态体现在什么环节就可以了。
那么,动态代理所描述的动态体现在哪里呢?主要体现在代理关系的维护上。

动态代理演示

首先,搞一个接口,描述下做什么事情:

/**
 * @author zhangjian
 * @version 1.0.0
 * @date 2021/11/16
 * @since 1.0.0
 */
public interface Work {
    /**
     * 写代码
     */
    void coding();
}

然后,描述个能够做这个事情的角色:

/**
 * @author zhangjian
 * @version 1.0.0
 * @date 2021/11/16
 * @since 1.0.0
 */
public final class JavaWork implements Work{
    @Override
    public void coding() {
        System.out.println("Java coding.....");
    }

}

最后,搞一个能够动态分配工作的角色:

/**
 * @author zhangjian
 * @version 1.0.0
 * @date 2021/11/16
 * @since 1.0.0
 */
public final class WorkHandler implements InvocationHandler {

    private  Object target;

    public WorkHandler(Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    /**
     * 售前团队
     */
    private void before() {
        System.out.println("工作没有被代理之前,售前先和你聊聊");
    }

    /**
     * 售后团队
     */
    private void after() {
        System.out.println("工作被代理以后,售后和你聊聊");
    }
}

接下来,准备一段测试代码:

/**
 * @author zhangjian
 * @version 1.0.0
 * @date 2021/11/16
 * @since 1.0.0
 */
public class SimpleDynamic {
    public static void main(String[] args) {
        // 找到一个程序员
        JavaWork javaWork = new JavaWork();

        // 找到这个程序员的领导
        ClassLoader classLoader = javaWork.getClass().getClassLoader();

        // 分析一下这个程序员都会什么开发语言
        Class[] interfaces = javaWork.getClass().getInterfaces();

        // 针对这个程序员制定一个工作流程
        WorkHandler workHandler = new WorkHandler(javaWork);

        // 制定工作计划,并按照工作流程分派给程序员
        Work work = (Work) Proxy.newProxyInstance(classLoader, interfaces, workHandler);

        // 程序员开始执行工作计划
        work.coding();
    }
}

补充内容

第一、在上述演示代码中,一些Java类做了final标记。final除了能够阻断类的继承关系以外,还有一个特别值得关注的问题就是能够规避类间关系检测,在类加载环节有提速的效果。

第二、在WorkHandler中,我增加了before()after()两个方法,用于模拟演示前置处理器和后置处理器,它不属于动态代理的内容。但是在动态代理中,经常这么玩。

第三、上文描述的动态代理实际上是基于JDK进行实现的,除此之外基于CGLIB的动态代理也是出镜频率很高的一种实现方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值