代理模式

转自 http://blog.csdn.net/briblue/article/details/73928350

参考:https://www.jianshu.com/p/58759fef38b8

一、静态代理

package com.proxy.test;

/**
 * 首先得有一个接口,通用的接口是代理模式实现的基础。这个接口我们命名为 Movie,代表电影播放的能力
 * @author Yuanjingkun
 *
 */
public interface Movie {
    void play();
}
package com.proxy.test;
/**
 * 真正实现 Movie接口的类,这个表示真正的影片。它实现了 Movie 接口,play() 方法调用时,影片就开始播放
 * @author Yuanjingkun
 *
 */
public class RealMovie implements Movie {

    @Override
    public void play() {
        System.out.println("您正在观看电影 《肖申克的救赎》");
    }

}
package com.proxy.test;
/**
 * 只是实现接口的代理类,Cinema 就是 Proxy 代理对象,它有一个 play() 方法。不过调用 play() 方法时,它进行了一些相关利益的处理,那就是广告。
 * @author Yuanjingkun
 *
 */
public class Cinema implements Movie {

    RealMovie movie;

    public Cinema(RealMovie movie) {
        
        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折,买回家吃吧!");
        }
    }

}
package com.proxy.test;

/**
 * @author Yuanjingkun
 *
 */
public class ProxyTest {

    public static void main(String[] args) {

        RealMovie realmovie = new RealMovie();

        Movie movie = new Cinema(realmovie);

        movie.play();

    }

}

结果:

电影马上开始了,爆米花、可乐、口香糖9.8折,快来买啊!
您正在观看电影 《肖申克的救赎》
电影马上结束了,爆米花、可乐、口香糖9.8折,买回家吃吧!

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

二 、动态代理

package com.frank.test;

public interface SellWine {

    /**
     * 卖酒
     */
    void maiJiu();
    
}
package com.frank.test;

public interface SellCigarette {

    /**
     * 卖烟
     */
    void maiYan();
    
}
package com.frank.test;

public class MaotaiJiu implements SellWine{

    @Override
    public void maiJiu() {
        
        System.out.println("我卖的是茅台酒");
        
    }
}
package com.frank.test;

public class Wuliangye implements SellWine{

    @Override
    public void maiJiu() {
        
        System.out.println("我卖的是五粮液");
        
    }
}
package com.frank.test;

public class Furongwang implements SellCigarette{

    @Override
    public void maiYan() {
        // TODO Auto-generated method stub
        System.out.println("售卖的是芙蓉王,可以扫码查证");
    }
}
package com.frank.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class GuitaiA implements InvocationHandler{

    private Object pinpai;
    
    public GuitaiA(Object pinpai){
        this.pinpai = pinpai;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("销售开始 柜台是:"+this.getClass().getSimpleName());
        method.invoke(pinpai, args);
        System.out.println("销售结束");
        return null;
    }
}
package com.frank.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {
        
        MaotaiJiu maotaijiu = new MaotaiJiu();
        Wuliangye wuliangye = new Wuliangye();
        Furongwang furongwang = new Furongwang();
        InvocationHandler jingxiao1 = new GuitaiA(maotaijiu);
        InvocationHandler jingxiao2 = new GuitaiA(wuliangye);
        InvocationHandler jingxiao3 = new GuitaiA(furongwang);
        
        SellWine dynamicProxyMaotai = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(), MaotaiJiu.class.getInterfaces(), jingxiao1);
        SellWine dynamicProxyWuliangye = (SellWine) Proxy.newProxyInstance(Wuliangye.class.getClassLoader(), Wuliangye.class.getInterfaces(), jingxiao2);
        SellCigarette dynamicProxyFurongwang = (SellCigarette) Proxy.newProxyInstance(Furongwang.class.getClassLoader(), Furongwang.class.getInterfaces(),jingxiao3);
        dynamicProxyMaotai.maiJiu();
        dynamicProxyWuliangye.maiJiu();
        dynamicProxyFurongwang.maiYan();
        System.out.println(dynamicProxyMaotai.getClass().getName());
    }
}

结果:

销售开始 柜台是:GuitaiA
我卖的是茅台酒
销售结束
销售开始 柜台是:GuitaiA
我卖的是五粮液
销售结束
销售开始 柜台是:GuitaiA
售卖的是芙蓉王,可以扫码查证
销售结束
com.sun.proxy.$Proxy0

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

总结

  1. 代理分为静态代理和动态代理两种。
  2. 静态代理,代理类需要自己编写代码写成。
  3. 动态代理,代理类通过 Proxy.newInstance() 方法生成。
  4. 不管是静态代理还是动态代理,代理与被代理者都要实现两样接口,它们的实质是面向接口编程。
  5. 静态代理和动态代理的区别是在于要不要开发者自己定义 Proxy 类。
  6. 动态代理通过 Proxy 动态生成 proxy class,但是它也指定了一个 InvocationHandler 的实现类。
  7. 代理模式本质上的目的是为了增强现有代码的功能。
原文地址:https://www.cnblogs.com/thiaoqueen/p/8054091.html