当前位置: 首页 > news >正文

Retrofit原理解析(二)

前言

上一篇我们分析了Retrofit是如何对OkHttp进行封装,而从完成网络请求的
Retrofit原理解析(一),这里我们来浅谈一下Retrofit源码中使用的优秀的设计模式

Retrofit中涉及的设计模式

外观设计模式

定义:系统外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

Retrofit 对客户端模块提供统一接口,Retrofit 类内部封装了 ServiceMethod、CallAdapter 和 Converter 等组件。并且 CallAdapter 和 Converter 都是抽象为接口,用户可以扩展自定义的实现。

相关源码

public final class Retrofit {
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl;
  final List<Converter.Factory> converterFactories;
  final List<CallAdapter.Factory> callAdapterFactories;
  final @Nullable Executor callbackExecutor;
  final boolean validateEagerly;

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
  ...
}

建造者设计模式

定义:指将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示,属于创建型设计模式。

一般当构造函数的参数>4个,且存在可选参数的时候可以考虑使用建造者模式;

Retrofit 对象使用建造者模式通过Builder类构建。

相关源码

  public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

动态代理设计模式

定义: 代理模式是结构型模式。当无法或不想直接访问某个对象,或者访问某个对象比较复杂的时候,可以通过一个代理对象来间接访问,代理对象向客户端提供和真实对象同样的接口功能。经典设计模式中,代理模式有四种角色:

Subject 抽象主题类:申明代理对象和真实对象共同的接口方法;

RealSubject 真实主题类:实现了 Subject 接口,真实执行业务逻辑的地方;

ProxySubject 代理类:实现了 Subject 接口,持有对 RealSubject 的引用,在实现的接口方法中调用 RealSubject 中相应的方法执行;

Cliect 客户端类:使用代理对象的类;

代理模式又分为静态代理动态代理:
静态代理在代码运行前 ProxySubject 代理类的 .class 编译文件就已存在;

动态代理是通过反射机制来动态生成方法接口的代理对象的。动态代理的实现是通过 JDK 提供的 InvocationHandler 接口,实现该接口重写其调用方法 invoke。

Retrofit中使用的正是动态代理设计模式,通过动态代理实现所有网络请求统一封装解析处理,这是Retrofit的核心设计思想;

相关源码

 public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

适配器设计模式

定义:适配器模式把一个类的接口变换成客户端所期待的另一个接口,从而使原本因接口不兼容而无法一起工作的两个类能一起工作。

Retrofit中,CallAdapter采用了适配器模式为创建访问Call接口提供服务。默认不添加Rxjava则使用默认的 ExecutorCallAdapterFactory 将okhttp3.call转变成为 retroift中的call,如果有Rxjava则将okhttp3.call转化为 Observable

相关源码

  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

装饰器设计模式

定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

Retrofit中,ExecutorCallbackCall使用装饰器模式来封装callbackExecutor,从而实现主线程切换功能;

相关源码

static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }

        public void enqueue(final Callback<T> callback) {
            Utils.checkNotNull(callback, "callback == null");
            this.delegate.enqueue(new Callback<T>() {
                public void onResponse(Call<T> call, final Response<T> response) {
                    ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
                        public void run() {
                            if (ExecutorCallbackCall.this.delegate.isCanceled()) {
                                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                            } else {
                                callback.onResponse(ExecutorCallbackCall.this, response);
                            }

                        }
                    });
                }

                public void onFailure(Call<T> call, final Throwable t) {
                    ExecutorCallbackCall.this.callbackExecutor.execute(new Runnable() {
                        public void run() {
                            callback.onFailure(ExecutorCallbackCall.this, t);
                        }
                    });
                }
            });
        }

        public boolean isExecuted() {
            return this.delegate.isExecuted();
        }

        public Response<T> execute() throws IOException {
            return this.delegate.execute();
        }

        public void cancel() {
            this.delegate.cancel();
        }

        public boolean isCanceled() {
            return this.delegate.isCanceled();
        }

        public Call<T> clone() {
            return new ExecutorCallAdapterFactory.ExecutorCallbackCall(this.callbackExecutor, this.delegate.clone());
        }

        public Request request() {
            return this.delegate.request();
        }
    }

策略设计模式

定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

Retrofit中,配置 Retrofit.Builder时addCallAdapterFactory,不同的CallAdapter都需要提供 adapt 方法,CallAdapter 就对应 Stragety 抽象策略。RxJavaCallAdapterFactory 的 get 方法返回 SimpleCallAdapter对象或 ResultCallAdapter 对象)就对应具体的策略实现。

相关源码

	T adapt(Call<R> call)

静态工厂设计模式

定义:我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。

Retrofit中,Platform创建就是采用静态工厂模式

相关源码

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
  }

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

相关文章:

  • 数据结构与算法 -- 子序列问题
  • python中namedtuple函数用法详解
  • C++设计模式---模板方法模式
  • 数据结构和算法——绪论
  • 最小生成树算法的相关变形题
  • Android中常用的几种容器视图的使用
  • 随手记面试录
  • VMware软件下载安装以及在VMware中安装Centos-stream
  • JCL入门教程
  • 5.6如何寻找最长回文子串
  • tkinter-event事件
  • Windows10环境gradle安装与配置
  • DELMIA弧焊虚拟仿真:带变位机的机器人弧焊焊接程序自动生成方法
  • Redis 非关系型数据库学习(三)---- Redis 基础知识
  • 离线数仓(2):数据仓库相关架构和规范
  • 【Leetcode】101. 对称二叉树
  • .pyc 想到的一些问题
  • 【css3】浏览器内核及其兼容性
  • CentOS7 安装JDK
  • es的写入过程
  • IP路由与转发
  • Kibana配置logstash,报表一体化
  • Laravel核心解读--Facades
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • PAT A1092
  • pdf文件如何在线转换为jpg图片
  • Python中eval与exec的使用及区别
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • 前端性能优化——回流与重绘
  • 区块链共识机制优缺点对比都是什么
  • 如何在 Tornado 中实现 Middleware
  • 使用Gradle第一次构建Java程序
  • 为视图添加丝滑的水波纹
  • 学习笔记:对象,原型和继承(1)
  • 运行时添加log4j2的appender
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 扩展资源服务器解决oauth2 性能瓶颈
  • # Apache SeaTunnel 究竟是什么?
  • #Linux(权限管理)
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (二)换源+apt-get基础配置+搜狗拼音
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (十五)使用Nexus创建Maven私服
  • (算法)求1到1亿间的质数或素数
  • (五)MySQL的备份及恢复
  • (一)UDP基本编程步骤
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • .NET 8.0 发布到 IIS
  • .net core使用ef 6
  • .net打印*三角形
  • .NET大文件上传知识整理
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件