• 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;
      }
      ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    建造者设计模式

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

    一般当构造函数的参数>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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    动态代理设计模式

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

    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);
              }
            });
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    适配器设计模式

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

    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);
          }
        };
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    装饰器设计模式

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

    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();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    策略设计模式

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

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

    相关源码

    	T adapt(Call<R> call)
    
    • 1

    静态工厂设计模式

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

    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();
      }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    结语

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

  • 相关阅读:
    Godot无法响应鼠标点击等输入事件时,检查这些内容
    C++11:智能指针
    人工智能三要素之算法Transformer
    深入理解强化学习——强化学习和有监督学习
    【经验】Word 2021|如何在Word里做出和Markdown中一样漂亮的引用样式(结尾附成品)
    Java 线程的调度与时间片
    公益培训报名小程序
    《算法设计与分析》第四章:贪心算法
    【学习推荐】极客时间-左耳听风专栏
    CSDN 云IDE体验报告
  • 原文地址:https://blog.csdn.net/a734474820/article/details/126613311