程序员

代理模式复习

2018-11-24  本文已影响5人  icecrea

静态代理

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

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

上一篇 下一篇

猜你喜欢

热点阅读