栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA 二十三种设计模式大全(十二)代理模式(Proxy Pattern)(三)动态代理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA 二十三种设计模式大全(十二)代理模式(Proxy Pattern)(三)动态代理

文章目录

改进(需求)设计代码总结

改进(需求)

我们的静态代理,只能代理一个固定的接口。
比如在(二)中,我们写了4个类去实现Movable接口,也就是4个类代理一个类。
那我如果现在多写一个Eatable接口,那我又需要再写4个类去代理它(假如要实现的功能与上面类似时)。
那这样似乎又是在重复堆砌了,能否有一种把所要代理的接口写活的方法呢?
让我们只需要写一次代理类,处处使用?

设计

把上面的需求描述转换一下,其实就是要让我们的代理类不再依附于被代理对象。
举例:
写一个日志代理类LogProxyFactory,它可以给任何类代理,在它们的运行前后添加日志,这样就实现了我们的目的:
不需要为被代理类重复写代理类。
说白了,如下图所示的位置,我们要做解耦。

代码

注:带$符号的都是代理类

public interface Movable {
    void move();
}
public class PeopleMovable implements Movable {
    // 人物移动是我们的主体行为
    // 理论上来讲,不需要嵌套到外部
    // 不过为了设计合理,也给它嵌套到外部的能力
    private Movable m;

    public PeopleMovable(Movable m) {
        this.m = m;
    }

    public PeopleMovable() {

    }

    @Override
    public void move() {
        if (m != null) {
            m.move();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("人物在移动");
    }
}

public class ProxyFactory {
//    甚至我们可以直接写ProxyFactory
//    而不做具体的日志类型 ,这样我们的代理工厂,可以代理任意类,也可以做任何形式的代理

    private Logger logger = LoggerFactory.getLogger("ProxyFactory");
    private Object target;

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

    public Object getLogTimeProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        long start = System.currentTimeMillis();
                        logger.info(this.getClass().getName() + "日志----------》开始");
                        Object invoke = method.invoke(target, args);
                        logger.info(this.getClass().getName() + "日志----------》结束");
                        long end = System.currentTimeMillis();
                        logger.info("耗时{}毫秒", end - start);
                        return invoke;
                    }
                });
    }

    public Object getTimeProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        long start = System.currentTimeMillis();
                        Object invoke = method.invoke(target, args);
                        long end = System.currentTimeMillis();
                        logger.info("耗时{}毫秒", end - start);
                        return invoke;
                    }
                });
    }

    public Object getLogProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        logger.info(this.getClass().getName() + "日志----------》开始");
                        Object invoke = method.invoke(target, args);
                        logger.info(this.getClass().getName() + "日志----------》结束");
                        return invoke;
                    }
                });
    }
}

public class MainProxyFactory {
    public static void main(String[] args) {
        // 串行的
        ProxyFactory proxyFactory = new ProxyFactory(new PeopleMovable());
        Movable logProxyInstance = (Movable) proxyFactory.getLogProxyInstance();
        logProxyInstance.move();
        System.out.println("------------------------->");
        Movable timeProxyInstance = (Movable) proxyFactory.getTimeProxyInstance();
        timeProxyInstance.move();
        System.out.println("------------------------->");
        //    再来个先日志后耗时的
        ProxyFactory proxyFactory1 = new ProxyFactory(timeProxyInstance);
        Movable logProxyInstance1 = (Movable) proxyFactory1.getLogProxyInstance();
        logProxyInstance1.move();
        System.out.println("------------------------->");
        //    也可以单独写个,这样调用方便了
        Movable logTimeProxyInstance = (Movable) proxyFactory.getLogTimeProxyInstance();
        logTimeProxyInstance.move();
        //    结果:
        //    09:44:52.800 [main] INFO ProxyFactory - proxypattern.ProxyFactory$3日志----------》开始
        //人物在移动
        //09:44:53.812 [main] INFO ProxyFactory - proxypattern.ProxyFactory$3日志----------》结束
        //------------------------->
        //人物在移动
        //09:44:54.823 [main] INFO ProxyFactory - 耗时1006毫秒
        //------------------------->
        //09:44:54.833 [main] INFO ProxyFactory - proxypattern.ProxyFactory$3日志----------》开始
        //人物在移动
        //09:44:55.839 [main] INFO ProxyFactory - 耗时1006毫秒
        //09:44:55.840 [main] INFO ProxyFactory - proxypattern.ProxyFactory$3日志----------》结束
        //------------------------->
        //09:44:55.847 [main] INFO ProxyFactory - proxypattern.ProxyFactory$1日志----------》开始
        //人物在移动
        //09:44:56.853 [main] INFO ProxyFactory - proxypattern.ProxyFactory$1日志----------》结束
        //09:44:56.854 [main] INFO ProxyFactory - 耗时1007毫秒
    }
}

总结

如上,把任意类的实例对象传入代理工厂,都可以实现代理,目前有日志和耗时,其他的也都可以继续往代理工厂补充。
这样实现了代理类与被代理类的解耦,一次编码处处代理^^

总而言之,代理模式中的动态代理算是设计模式中比较难理解的
主要是利用了java中的
java.lang.reflect.Proxy
这个类

所以也称为JDK动态代理
含义就是这种代理是利用了JDK的API实现的

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/732564.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号