白话设计模式之代理模式

2022-07-26 16:57:41 浏览数 (1)

代理模式介绍

代理模式,顾名思义,代理就是不自己做,让别人来帮忙做,现实中有很多例子,比如中介公司,婚介所,这些都是代理典型的代理机构,比如我想找一个女朋友,但是由于我的脸皮比较薄,不好意思和女孩子说话,更没有搭讪的勇气,于是乎,我找到了我的好朋友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老师吧

0 人点赞