前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >白话设计模式之代理模式

白话设计模式之代理模式

作者头像
小四的技术之旅
发布2022-07-26 16:57:41
1940
发布2022-07-26 16:57:41
举报
文章被收录于专栏:小四的技术文章

代理模式介绍

代理模式,顾名思义,代理就是不自己做,让别人来帮忙做,现实中有很多例子,比如中介公司,婚介所,这些都是代理典型的代理机构,比如我想找一个女朋友,但是由于我的脸皮比较薄,不好意思和女孩子说话,更没有搭讪的勇气,于是乎,我找到了我的好朋友mikey老师,让他给我介绍一下,他答应了我的请求,于是我就去专心写代码了,女朋友的事情就交在他身上了,我不去瞎操心了。

Java语言来表示这一过程

定义一个接口

代码语言:javascript
复制
public interface IPeople {
    //找女朋友
    void findGirlFriend();
}

单身狗steakliu委托mikey老师帮忙找女朋友

代码语言:javascript
复制
public class Steak implements IPeople{
    private final MikeyTeacher mikeyTeacher;
    public Steak(MikeyTeacher mikeyTeacher){
        this.mikeyTeacher = mikeyTeacher;
    }
    @Override
    public void findGirlFriend() {
        System.out.println("steak: 我想找一个女朋友,委托了mikey老师帮我找");
        //委托mikey老师去找
        mikeyTeacher.findGirlFriend();
        System.out.println("steak: mikey老师给我找到了女朋友,我现在开始交往了");
    }
}

mikey老师

代码语言:javascript
复制
public class MikeyTeacher implements IPeople{
    @Override
    public void findGirlFriend() {
        System.out.println("mikey: 接受了steak的请求,我现在疯狂的帮他找女朋友");
    }
}

测试

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        Steak steak = new Steak(new MikeyTeacher());
        steak.findGirlFriend();
    }
}

输出:
  steakliu: 我想找一个女朋友,委托了mikey老师帮我找
  mikey: 接受了steakliu的请求,我现在疯狂的帮他找女朋友
  steakliu: mikey老师给我找到了女朋友,我现在开始交往了

自从mikey老师给我介绍成功了女朋友过后,在圈内传开了名,大群的单身狗都找到了mikey老师,当然mikey老师也是很乐意的,不过现在mikey老师只能服务steakliu一个人(静态代理),于是mikey老师从新改造了下自己,不再只为steakliu服务,而是为更多的单身狗服务(Jdk动态代理),现在mikey老师啥也不说,就开始改造了。

接口依然没有变

代码语言:javascript
复制
public interface IPeople {
    //找女朋友
    void findGirlFriend();
}

mikey老师,实现了InvocationHandler 接口

代码语言:javascript
复制
public class MikeyProxyTeacher implements InvocationHandler {

    private IPeople people;
    //获取对象实例
    public IPeople getPeopleInstance(IPeople people){
        this.people = people;
        return (IPeople) Proxy.newProxyInstance(people.getClass().getClassLoader(),people.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("mikey老师:我现在开始帮广大单身网友找女朋友");
        Object response = method.invoke(people,args);
        System.out.println("mikey老师:为单身网友找到女朋友");
        return response;
    }
}

单身狗steakliu

代码语言:javascript
复制
public class Steak implements IPeople {
    @Override
    public void findGirlFriend() {
        System.out.println("单身网友steak: 我想找一个女朋友,委托了mikey老师帮我找");
    }
}

测试

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        MikeyProxyTeacher mikeyProxyTeacher = new MikeyProxyTeacher();
        IPeople instance = mikeyProxyTeacher.getPeopleInstance(new Steak());
        instance.findGirlFriend();
    }
}

结果
  mikey老师:我现在开始帮广大单身网友找女朋友
  单身网友steakliu: 我想找一个女朋友,委托了mikey老师帮我找
  mikey老师:为单身网友找到女朋友

现在单身网友tlgen也想找一个女朋友,找到了mikey老师,于是只需要拿到mikey老师的“介绍说明书”,就可以了

代码语言:javascript
复制
public class Tlgen implements IPeople {
    @Override
    public void findGirlFriend() {
        System.out.println("单身网友tlgen: 我想找一个女朋友,委托了mikey老师帮我找");
    }
}

测试

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        MikeyProxyTeacher mikeyProxyTeacher = new MikeyProxyTeacher();
        IPeople instance = mikeyProxyTeacher.getPeopleInstance(new Tlgen());
        instance.findGirlFriend();
    }
}

结果
  mikey老师:我现在开始帮广大单身网友找女朋友
  单身网友tlgen: 我想找一个女朋友,委托了mikey老师帮我找
  mikey老师:为单身网友找到女朋友

mikey老师的介绍的人越来越多,这时候,只是每个网友都需要拿到mikey老师的“介绍说明书”(实现接口),mikey老师才能帮其介绍女朋友,很多网友不愿意了,于是mikey老师又想出了一个策略,网友不用拿到“介绍说明书”也行(cglib动态代理),mikey老师开始改造。

mikey老师实现了MethodInterceptor 接口

代码语言:javascript
复制
public class MikeyCglibProxyTeacher implements MethodInterceptor {

    private final Enhancer enhancer = new Enhancer();

    public Object getProxy(Class<?> clazz){
        if (clazz == null){
            throw new RuntimeException("get object instance the param does not null");
        }
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("mikey老师:我现在开始帮广大单身网友找女朋友");
        Object response = methodProxy.invokeSuper(o, objects);
        System.out.println("mikey老师:为单身网友找到女朋友");
        return response;
    }
}

这时单身网友JiaCong和哥几个来找女朋友了。

代码语言:javascript
复制
public class JiaCong {
    public void findGirlFriend() {
        System.out.println("单身网友JiaCong: 我想找一个女朋友,委托了mikey老师帮我找");
    }
}

mikey老师帮JiaCong开始找女朋友

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        MikeyCglibProxyTeacher mikeyCglibProxyTeacher = new MikeyCglibProxyTeacher();
        JiaCong proxy = (JiaCong) mikeyCglibProxyTeacher.getProxy(JiaCong.class);
        proxy.findGirlFriend();
    }
}

结果
  mikey老师:我现在开始帮广大单身网友找女朋友
  单身网友JiaCong: 我想找一个女朋友,委托了mikey老师帮我找
  mikey老师:为单身网友找到女朋友

总结

mikey老师和单身狗网友的故事就讲完了,从中我们引出了静态代理,Jdk动态代理和cglib动态代理,Jdk动态代理是代理接口,cglib动态代理是代理类,二者都有不同的使用场景,需要根据自己的需求去选择。

使用场景

代理模式使用也十分频繁,比如spring的aop就是典型的代理模式,aop切面就是将与主业务不相关的功能抽离出来,通过切面的方式去使用,比如日志记录,接口权限等。

最后单身狗朋友们赶快去找mikey老师吧

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 刘牌 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档