學(xué)習(xí)源碼-Retrofit之用到的設(shè)計模式

參考:手把手帶你 深入讀懂 Retrofit 2.0 源碼

建造者模式Builder

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.serverUrl())
                .client(okHttpClient)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();



ServiceMethod<?, ?> result = new ServiceMethod.Builder<>(this, method).build();

建造者模式:將一個復(fù)雜對象的構(gòu)建與表示分離,使得用戶在不知道對象的創(chuàng)建細(xì)節(jié)情況下就可以直接創(chuàng)建復(fù)雜的對象。具體請看文章:建造者模式(Builder Pattern)- 最易懂的設(shè)計模式解析

工廠模式Factory

RxJava2CallAdapterFactory

GsonConverterFactory

將“類實例化的操作”與“使用對象的操作”分開,使得使用者不用知道具體參數(shù)就可以實例化出所需要的“產(chǎn)品”類。
簡單工廠模式(SimpleFactoryPattern)- 最易懂的設(shè)計模式解析
工廠方法模式(Factory Method)- 最易懂的設(shè)計模式解析
抽象工廠模式(Abstract Factory)- 最易懂的設(shè)計模式解析

策略模式

//在Retrofit中提供了四種CallAdapterFactory: ExecutorCallAdapterFactory(默認(rèn))、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory
//采用了策略模式

指對象有某個行為,但是在不同的場景中,該行為有不同的實現(xiàn)方法。

外觀模式

public interface IIndexApi {
    /**
     * banner
     *
     * @param type 類型
     * @return Observable
     */
    @GET("/rest/api/index")
    Observable<HeadData> getData(@Header("x-token") String tokenStr,@Query("type") String type);
}

定義一個統(tǒng)一接口,外部與通過該統(tǒng)一的接口對子系統(tǒng)里的其他接口進(jìn)行訪問。具體請看:外觀模式(Facade Pattern) - 最易懂的設(shè)計模式解析

代理模式

(T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @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);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });

通過訪問代理對象的方式來間接訪問目標(biāo)對象

  1. 靜態(tài)代理:代理類在程序運行前已經(jīng)存在的代理方式
  2. 動態(tài)代理:代理類在程序運行前不存在、運行時由程序動態(tài)生成的代理方式
    具體請看文章代理模式(Proxy Pattern)- 最易懂的設(shè)計模式解析

裝飾模式

  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;
    }

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

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

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }

把上面創(chuàng)建并配置好參數(shù)的OkhttpCall對象交給靜態(tài)代理delegate
靜態(tài)代理和動態(tài)代理都屬于代理模式
靜態(tài)代理作用:代理執(zhí)行被代理者的方法,且可在要執(zhí)行的方法前后加入自己的動作,進(jìn)行對系統(tǒng)功能的拓展

采用了裝飾模式:ExecutorCallbackCall = 裝飾者,而里面真正去執(zhí)行網(wǎng)絡(luò)請求的還是OkHttpCall
使用裝飾模式的原因:希望在OkHttpCall發(fā)送請求時做一些額外操作。這里的額外操作是線程轉(zhuǎn)換,即將子線程切換到主線程
OkHttpCall的enqueue()是進(jìn)行網(wǎng)絡(luò)異步請求的:當(dāng)你調(diào)用OkHttpCall.enqueue()時,回調(diào)的callback是在子線程中,需要通過Handler轉(zhuǎn)換到主線程進(jìn)行回調(diào)。ExecutorCallbackCall就是用于線程回調(diào);
當(dāng)然以上是原生Retrofit使用的切換線程方式。如果你用Rxjava,那就不會用到這個ExecutorCallbackCall而是RxJava的Call

適配器模式

  static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Retrofit 2 源碼解析 關(guān)于Retrofit 2的使用請看上一篇https://www.jianshu.c...
    gogoingmonkey閱讀 661評論 0 1
  • 前言 注解式的框架非?;穑⒔庖云漭p量,簡潔等特性被人們所喜愛者,關(guān)鍵是它解藕。網(wǎng)絡(luò)請求的框架非常多,比較受歡迎的...
    薩達(dá)哈魯醬閱讀 627評論 0 5
  • Retrofit 是目前作為網(wǎng)絡(luò)請求的主流框架,使用起來很方便,僅需在接口中定義方法,打上注解,而且和 Rxjav...
    Kip_Salens閱讀 684評論 0 3
  • 適配器模式上一篇文章我們已經(jīng)分析了Retrofit解析注解封裝進(jìn)ServiceMethod的流程,讀者在這里要記住...
    andcoder閱讀 772評論 0 2
  • 總有些生命,酣暢淋漓地恣意揮灑,哪怕是遍體鱗傷。亦有些生命,寧靜淡泊地安于一隅,哪怕無波無瀾,然則平,亦可...
    人生夢想閱讀 849評論 2 5

友情鏈接更多精彩內(nèi)容