美文网首页程序员
代理模式复习

代理模式复习

作者: icecrea | 来源:发表于2018-11-24 16:40 被阅读5次

    静态代理

    代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。

    public interface Movie {
        void play();
    }
    

    真正的实现类

    public class RealMovie implements Movie {
    
        @Override
        public void play() {
            // TODO Auto-generated method stub
            System.out.println("您正在观看电影 《肖申克的救赎》");
        }
    
    }
    
    
    

    静态代理 对movie进行代理

    public class Cinema implements Movie {
    
        RealMovie movie;
    
        public Cinema(RealMovie movie) {
            super();
            this.movie = movie;
        }
    
    
        @Override
        public void play() {
    
            guanggao(true);
    
            movie.play();
    
            guanggao(false);
        }
    
        public void guanggao(boolean isStart){
            if ( isStart ) {
                System.out.println("电影马上开始了,爆米花、可乐、口香糖9.8折,快来买啊!");
            } else {
                System.out.println("电影马上结束了,爆米花、可乐、口香糖9.8折,买回家吃吧!");
            }
        }
    
    }
    
    public class ProxyTest {
    
        public static void main(String[] args) {
    
            RealMovie realmovie = new RealMovie();
    
            Movie movie = new Cinema(realmovie);
    
            movie.play();
    
        }
    
    }
    

    动态代理

    上面代码中 Cinema 类是代理,我们需要手动编写代码让 Cinema 实现 Movie 接口,而在动态代理中,我们可以让程序在运行的时候自动在内存中创建一个实现 Movie 接口的代理,而不需要去定义 Cinema 这个类。这就是它被称为动态的原因。

    假设有一个大商场,商场有很多的柜台,有一个柜台卖茅台酒

    
    //卖酒的许可证
    public interface SellWine {
     
         void mainJiu();
     
    }
    
    public class MaotaiJiu implements SellWine {
     
        @Override
        public void mainJiu() {
            // TODO Auto-generated method stub
            System.out.println("我卖得是茅台酒。");
     
        }
     
    }
    
    public class GuitaiA implements InvocationHandler {
     
        private Object pingpai;
     
     
        public GuitaiA(Object pingpai) {
            this.pingpai = pingpai;
        }
     
     
     
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("销售开始  柜台是: "+this.getClass().getSimpleName());
            method.invoke(pingpai, args);
            System.out.println("销售结束");
            return null;
        }
     
    }
     
    
     
    public class Test {
     
        public static void main(String[] args) {
            // TODO Auto-generated method stub
     
            MaotaiJiu maotaijiu = new MaotaiJiu();
     
     
            InvocationHandler jingxiao1 = new GuitaiA(maotaijiu);
     
     
            SellWine dynamicProxy = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(),
                    MaotaiJiu.class.getInterfaces(), jingxiao1);
     
            dynamicProxy.mainJiu();
     
        }
     
    }
    

    方法解析

    public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
    

    loader 自然是类加载器,interfaces 代码要用来代理的接口,h 一个 InvocationHandler 对象

    InvocationHandler
    InvocationHandler 是一个接口,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。

    因为,Proxy 动态产生的代理会调用 InvocationHandler 实现类,所以 InvocationHandler 是实际执行者。


    红框中 $Proxy0 就是通过 Proxy 动态生成的。
    $Proxy0 实现了要代理的接口。
    $Proxy0 通过调用 InvocationHandler 来执行任务。

    上一篇代理模式回顾:
    https://www.jianshu.com/p/ed281dcf9fa7
    参考文章:
    https://blog.csdn.net/briblue/article/details/73928350

    相关文章

      网友评论

        本文标题:代理模式复习

        本文链接:https://www.haomeiwen.com/subject/nrryqqtx.html