Android设计模式

设计模式笔记三代理模式

2017-03-11  本文已影响6人  summer_lz

每日一文

捭阖之道,以阴阳试之,故与阳言者依崇高,与阴言者依卑小。以下求小,以高求大。由此言之,无所不出,无所不入,无所不可。可以说人,可以说家,可以说国,可以说天下。
关于开放和封闭的规律都要从有阳两方面来试验。因此,给从阳的方面来游说的人以崇高的待遇,而给从阴的方面来游说的人以卑下的待遇。用卑下的来求索微小,以崇高来求索博大。由此看来,没有什么不能出去,没有什么不能进来,没有什么办不成的。用这个道理,可以说服人,可以说服家,可以说服国,可以说服天下。

代理模式


作用

原有类的行为基础上,加入一些多出的行为,甚至完全替换原有的行为。


代理模式中的角色:

两种形式:

指程序员创建好代理类,编译时直接生成代理类的字节码文件。

特点:

代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。而且代理类只能为特定的接口(Service)服务。

示例:
  1. 统一的抽象接口:
package com.bankht.Proxy;
public abstract class AbstractObject {
      // 操作
      public abstract void operation();
}
  1. 目标类:
package com.bankht.Proxy;
public class RealObject extends AbstractObject {
      @Override
      public void operation() {
        // 一些操作
        System.out.println("一些操作");
      }
 }
  1. 静态代理类:对目标类的封装
package com.bankht.Proxy;
public class ProxyObject extends AbstractObject {
      RealObject realObject = new RealObject();

      @Override
      public void operation() {
        // 调用目标对象之前可以做相关操作
        System.out.println("before");
        realObject.operation();
        // 调用目标对象之后可以做相关操作
        System.out.println("after");
      }
}
  1. 客户端调用:
package com.bankht.Proxy;
public class Client {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        AbstractObject obj = new ProxyObject();
        obj.operation();
      }
}

代理类可代理一系列类的特定方法,代理类需要实现InvocationHandler接口。

特点:

如果需要委托类处理某一业务,那么我们就可以先在代理类中,对客户的权限、各类信息先做判断,如果不满足某一特定条件,则将其拦截下来,不让其代理。

示例:
  1. 代理的接口:代码引用需要空行
    package com.example.patternproxy;

        import java.util.Date;
        
        /**
         * Created on 2017/3/11.
         * Desc:代理的接口
         * Author:Eric.w
         */
        
        public interface DateSerice {
        
            String queryDate();
        
            int cauOld(Date startdate);
        }
    
  2. 被代理的类:

     package com.example.patternproxy;
    
     import android.util.Log;
    
     import java.text.SimpleDateFormat;
     import java.util.Date;
    
     /**
     * Created on 2017/3/11.
     * Desc:
     * Author:Eric.w
     */
    
     public class DateServiceImp implements DateSerice {
    
        SimpleDateFormat myFmt = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
    
        @Override
        public String queryDate() {
            Date date = new Date();
            Log.e("pattern", "时间是:" + myFmt.format(date));
            return myFmt.format(date);
        }
    
        @Override
        public int cauOld(Date startdate) {
            return new Date().getYear() - startdate.getYear();
        }
    
        public String ownMethod() {
            Log.e("pattern", "ownMethod:");
            return "admin";
        }
     }
    
  3. 代理类

public Object invoke(Object proxy, Method method, Object[] args) throws    Throwable {
          System.out.println("before");
          Method sourceMethod = source.getClass().getDeclaredMethod(method.getName(),  method.getParameterTypes());
        sourceMethod.setAccessible(true);
          Object result = sourceMethod.invoke(source, args);
          System.out.println("after");
          return result;
    }

这就与你实现接口的表现行为一致了,但是我们本来就只需要一句method.invoke就可以了,就因为没实现接口就要多写两行,所以这种突破JDK动态代理必须实现接口的行为就有点画蛇添足了。因为你本来就实现了该接口的方法,只是差了那一句implements而已。
上面写这个例子只是为了解释LZ当初的疑惑,因为LZ曾一度认为不实现接口就不能使用动态代理

  1. 代码
    import android.util.Log;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * Created on 2017/3/11.
     * Desc:
     * Author:Eric.w
     */
    
    public class DateProxy implements InvocationHandler {
    
        private Object target;
    
        public DateProxy(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (DateSerice.class.isAssignableFrom(proxy.getClass()) &&
                    method.getName().equals("queryDate")) {
                //调用代理
                Log.e("pattern", "方法来自代理!");
                return null;
            }
            //不调用代理
            return method.invoke(proxy, args);
        }
    
        /**
         * 返回被代理的类实例
         *
         * @return
         */
        public Object getProxyInstance() {
            return Proxy.newProxyInstance(target.getClass().getClassLoader()
                    , target.getClass().getInterfaces()
                    , this);
        }
    }

讲解动态代理的原理

上一篇 下一篇

猜你喜欢

热点阅读