Android设计模式---代理模式

一.核心思想

为其他对象提供代理以控制对这个对象的访问,代理对象起到了中介作用,不影响其他对象原有的功能,可以在其基础上新增额外的服务。

解释: A要访问a, A--->B(代理)--->a, 这个过程B代理可以做一些扩展性的东西, 而且不会影响a原有的功能.

二. 分类

1. 静态代理:
2. 动态代理

三. 简单实现

例如: 计算吃饭时间
如果不使用代理的情况

public interface IDinner {
    String TAG = "66";
    void eat();
}

public class LiysBusiness implements IDinner {
    @Override
    public void eat() {
        Log.d(TAG, "开始时间: " +new Date().getTime());
        Log.d(TAG, "liys吃饭");
        Log.d(TAG, "结束时间: " +new Date().getTime());
    }
}

这种方式有个致命的缺点:
如果想分别计算几百人吃饭的时间, 那重复的代码就多了去.
下面我们看看怎么用代理模式解决这个问题的.

1.静态代理

public class LiysBusiness implements IDinner {
    @Override
    public void eat() {
        Log.d(TAG, "liys吃饭");
    }
}

public class HongDinner implements IDinner {
    @Override
    public void eat() {
        Log.d(TAG, "hong吃饭");
    }
}

代理类

public class ProxyDinner implements IDinner {

    IDinner mIDinner;

    public ProxyDinner(@NonNull IDinner iDinner){
        this.mIDinner = iDinner;
    }

    @Override
    public void eat() {
        if(mIDinner != null){
            Log.d(TAG, "开始时间: " +new Date().getTime());
            mIDinner.eat();
            Log.d(TAG, "结束时间: " +new Date().getTime());
        }
    }
}
//使用
//liys
ProxyBusiness proxyDinner = new ProxyBusiness(new LiysBusiness());
proxyDinner.handle();

//hong
proxyDinner = new ProxyBusiness(new HongBusiness());
proxyDinner.handle();

打印结果:


Android设计模式---代理模式_第1张图片
log1.png

这样就解决了上面的问题了.
使用静态代理的好处:
①. 降低耦合性, 每个实现类只需要做属于自己的事情, 其它不需要管, 符合单一职责原则.
②. 扩展性强, 实现类的逻辑不用做任何改变, 即可实现, 符合开闭原则

思考: 这样是不是就完美了呢? 如果我想计算洗澡的时间, 是不是还得写多一个洗澡的代理类ProxyBathe, 如果我还想计算睡觉的时间呢? 等等.这个时候代理类就会越来越多. 怎么办呢? 能不能用一个代理类解决这些问题? 这个时候就得看动态代理了.

2. 动态代理
Java里面其实为我们提供了一套动态代理机制, 我们先看关键类InvocationHandler(其实是一个接口).

package java.lang.reflect;
public interface InvocationHandler {

  /**
   * @param proxy 被代理的对象
   * @param method 被代理的方法
   * @param args 被代理方法参数
   * @return 返回代理对象
   * @throws Throwable
   */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

下面看具体实现

/**
 * 代理类(计算时间)
 */
public class TimeInvocationHandler implements InvocationHandler{

    String TAG = "66";
    //被代理的对象
    private Object mObject;

    public TimeInvocationHandler(Object object){
        this.mObject = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Log.d(TAG, "开始时间: " +new Date().getTime());
        Object voidObject = method.invoke(mObject,args);
        Log.d(TAG, "结束时间: " +new Date().getTime());
        return voidObject;
    }
}

//新增洗澡功能

public interface IBathe {
    String TAG = "66";
    void bathe();
}

public class Bathe implements IBathe{
    public void bathe(){
        try {
            Log.d(TAG, "洗澡..");
            Thread.sleep(123);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

//使用

// 返回的是 IBank 的一个实例对象,这个对象是由 Java 给我们创建的 ,调用的是 jni
    //计算吃饭时间
    IDinner iDinner = (IDinner) Proxy.newProxyInstance(
                        IDinner.class.getClassLoader(), // ClassLoader
                        new Class[]{IDinner.class}, // 目标接口
                        new TimeInvocationHandler(new LiysDinner()) //TimeInvocationHandler (这个类是关键)
    );
    iDinner.eat();
    
    //计算洗澡时间
    IBathe iBathe = (IBathe) Proxy.newProxyInstance(
                        IBathe.class.getClassLoader(),
                        new Class[]{IBathe.class},
                        new TimeInvocationHandler(new Bathe())
    );
    iBathe.bathe();

打印结果:


Android设计模式---代理模式_第2张图片
log2.png

这样就解决问题了, 以上就是动态代理的简单实现.
如果想深入了解Proxy工作原理, 请参考: Proxy.newProxyInstance的秘密

四. 实战篇

源码这里只是大概介绍, 重点还是在动态代理
Retrofit的创建
首先我们看Retrofit最简单的运用, 用过的应该都能看懂.

public interface ServiceApi {

    @POST("api/liys/login")// 登录接口 GET(相对路径)
    Call userLogin(
            // @Query(后台需要解析的字段)
            @Query("userName") String userName,
            @Query("password") String userPwd);
}
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://192.168.1.201")
                .addConverterFactory(ScalarsConverterFactory.create()) //返回值解析成String
                .build();
        // 创建一个 实例对象
        ServiceApi mServiceApi = retrofit.create(ServiceApi.class);

        mServiceApi.userLogin("123", "456")
              .enqueue(new Callback() {
                  @Override
                  public void onResponse(Call call, Response response) {}
                  @Override
                  public void onFailure(Call call, Throwable t) {}
        });

一开始看到这种用法的时候, 我一脸懵逼, 非常不习惯, 后面才慢慢习惯. 我们这里重点关注这行代码:

ServiceApi mServiceApi = retrofit.create(ServiceApi.class);

看看retrofit.create源码(版本:2.3.0): 省略部分代码

 public  T create(final Class service) {
    //检测传进来的service是否是接口, 如果不是则抛出异常throw new IllegalArgumentException("API declarations must be interfaces.");
    Utils.validateServiceInterface(service);

    //动态代理(重点)
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[] { service },
        new InvocationHandler() {
         
          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            //执行接口上的方法时都要先进到这个方法里, 例如:mServiceApi.userLogin("123", "456")
            // 解析接口上的注解 和 方法参数, 经过一系列的操作,封装成Call或别的对象返回去
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

你可能感兴趣的:(Android设计模式---代理模式)