设计模式【代理模式】

来源:互联网 发布:长棍佯谬知乎 编辑:程序博客网 时间:2024/06/03 15:03

       首先我们先了解代理,代理是指一个人或者一个机构代表另一个人或者机构采取行动。代理模式给某一个对象提供一个代理对象,并由代理对象控制对象控制对原对象的引用。
       代理模式一般涉及三个角色:
       Subject:抽象角色,声明真实对象和代理对象的共同接口;
    Proxy:代理角色,代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象鱼与真

实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。简言之,代理角色是业务逻辑的具体执行者。
    RealSubject:真实角色,代理角色所代表的真实对象,即我们最终要引用的对象。

案例场景:
       客户Client,通过手机代理商MobileProxy(Proxy)购买(获取)一部手机(Mobile),而真实手机提供商是手机工厂MobileFactory(RealSubject)。

【转载使用,请注明出处:http://blog.csdn.net/mahoking

演示程序:

/** * 物品商品对象 * @author Mahc */public class Mobile {public void call() {System.out.println("Mobile[合格]可以打电话!");}}/** * RealSubject * @author Mahc*/public class MobileFactory implements Factory {@Overridepublic Mobile produce() {return new Mobile();}}/** * Subject 抽象对象 * @author Mahc */public interface Factory {public Mobile produce();}/** * Proxy对象 * @author Mahc */public class MobileProxy implements Factory {private MobileFactory factory;/**MobileProxy 构造函数*/protected MobileProxy(MobileFactory mobileFactory) {this.factory = mobileFactory;}@Overridepublic Mobile produce() {return factory.produce();}}/** * 模拟客户对象 * @author Mahc */public class Client {public static void main(String[] args) {//真实的Mobile生产商MobileFactory mobileFactory = new MobileFactory();MobileProxy mobileProxy = new MobileProxy(mobileFactory);//使用MobileProxy对象的produce()方法,生产MobileMobile mobile = mobileProxy.produce();mobile.call();}}

       在此我们已经初步了解了设计模式中的代理模式,下面我们进一步了解代理模式中静态代理与动态代理的区别。
       静态代理(Static Proxy):真实对象和代理对象有共同的接口, 代理对象角色内部含有对真实对象的引用,从而可以操作
真实对象,同时代理对象提供与真实对象相同的方法。
       动态代理(Dynamic Proxy):真实对象和抽象对象有共同的接口,代理对象角色通过Java的反射机制

(java.lang.reflect.Method.newProxyIntance())获得,同时代理对象(为java.lang.reflect.InvocationHandler的子类通

过invoke())调用真实对象相同的方法。

       所以从综上所示可知,第一个演示案例为静态代理模式。下面我们提供动态代理模式的案例。本例所涉及的新的知识点需要读者和本人在平时不断补充与积累。例如反射机制的思想与相关的Java API,如果学习深入会发现这方面的学习会触及AOP(面向切面编程)。

动态代理案例:

/** * 获取动态代理对象的类 * @author Mahc * */public class ProxyHandler implements InvocationHandler{private Object object;public ProxyHandler(Object object) {this.object = object;}/** * 生成代理对象的静态方法 * @param realObject * @return */public static Object  getProxyIntance(Object realObject){Class<?> classType = realObject.getClass();        return Proxy.newProxyInstance(classType.getClassLoader(),                 classType.getInterfaces(),  new ProxyHandler(realObject));}/** * proxy 代理对象 * method 调用的方法 * args 方法的参数 */@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {if("produce".equalsIgnoreCase(method.getName())){System.out.println("执行了Mobile.call()");}Object resultObj = method.invoke(object, args);//System.out.println(resultObj.getClass());return resultObj;}}public class Client {public static void main(String[] args) {MobileFactory mobileFactory = new MobileFactory();Factory factory = (Factory) ProxyHandler.getProxyIntance(mobileFactory);Mobile mobile = factory.produce();mobile.call();}}


 下面我们来对比两种代理模式的优缺点。
       静态代理:
       优点:
              1、对象直观,静态代理是实实在在的存在的,我们创建编写。
              2、在编译期加入,提前就指定好使用对象,所以效率高。
       缺点:
              1、 代理对象与真实对象关联性高,所以需要代理多个真实对象时,需要大量的代理类。
              2、 在编译期加入关联对象,系统的灵活性差。

动态代理:
       优点:
             1、一个动态代理类可以简单解决创建多个静态代理的麻烦。
             2、调用目标代码时,会在方法“运行时”动态的加入,调用灵活。
       缺点:
             1、系统灵活了,但是相比而言,效率降低了,比静态代理慢一点。
             2、动态代理比静态代理在代码的可读性上差了一点,不太容易理解。
             3、JDK动态代理只能对实现了接口的类进行代理。(这个问题下面会介绍)

       静态代理VS动态代理,各自有各的独特之处,均不可代替,在项目中到底使用哪种代理模式,需要根据自身的需要来定。下面我们来解释上面遗留的问题,以上我们介绍的这种动态代理叫做jdk proxy即原生的jdk代理,它其实也不是完美的,它只能代理实现了接口的类如【MobileFactory implements Factory】,不能对类本身实现代理,要完成对类本身实现代理,需要用到另外一个开源的类库cglib【CGLIB(Code Generation Library)】,还有待继续我们平时不断学习与研究

【转载使用,请注明出处:http://blog.csdn.net/mahoking

1 0