retrofit第一步拆解 -- 構造者模式

weixin_34320159發表於2016-10-10

引言

關於retrofit原始碼解析的文章已經有很多了,我在拜讀了許多文章之後在此記錄一下,算是對retrofit的一個深入理解,以及其中用到的設計模式的學習。

構造者模式

構造者模式(Builder Pattern),將一個複雜物件的構建與它的表示分離,使的同樣的構建過程可以建立不同的表示。
構造者模式的優點是:使得建造程式碼與表示程式碼分離,由於建造者隱藏了該產品是如何組裝的,所以如要改變一個產品的內部表示,只需要再定義一個具體的建造者就可以了。

public class Student {

    private int id;
    private String name;
    private String passwd;
    private String sex;
    private String address;

    // 構造器儘量縮小範圍
    private Student() {
    }

    // 構造器儘量縮小範圍
    private Student(Student origin) {
        // 拷貝一份
        this.id = origin.id;
        this.name = origin.name;
        this.passwd = origin.passwd;
        this.sex = origin.sex;
        this.address = origin.address;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getPasswd() {
        return passwd;
    }

    public String getSex() {
        return sex;
    }

    public String getAddress() {
        return address;
    }

    /**
     * Student的建立完全依靠Student.Builder,使用一種方法鏈的方式來建立
     *
     */
    public static class Builder {

        private Student target;

        public Builder() {
            target = new Student();
        }

        public Builder address(int id) {
            target.id = id;
            return this;
        }

        public Builder name(String name) {
            target.name = name;
            return this;
        }

        public Builder password(String passwd) {
            target.passwd = passwd;
            return this;
        }

        public Builder sex(String sex) {
            target.sex = sex;
            return this;
        }

        public Builder address(String address) {
            target.address = address;
            return this;
        }

        public Student build() {
            return new Student(target);
        }   
    }
}

使用Student s=new Student.Builder().name("CC").password("qwerty").sex("男").address("銀河系第二旋臂").build();

Retrofit中的構造者模式

Retrofit retrofit = new Retrofit.Builder()
                .client(getOkHttpClient())
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
public Retrofit build() {
      // 必須得設定baseUrl,不然就直接丟擲異常
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      // 如果不設定okhttp3.Call.Factory,會預設直接new OkHttpClient();可見如果需要對okhttpclient進行詳細的設定,需要構建OkHttpClient物件,然後傳入;
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      // 用來將回撥傳遞到UI執行緒的。 這裡有一個platform物件,可以利用該物件進行平臺的判斷:如果是Android平臺,會自定義一個Executor物件,並且利用Looper.getMainLooper()例項化一個handler物件,在Executor內部通過handler.post(runnable)
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      // adapterFactories,這個物件主要用於對Call進行轉化,基本上不需要我們自己去自定義。
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      // converterFactories,該物件用於轉化資料,例如將返回的responseBody轉化為物件等;當然不僅僅是針對返回的資料,還能用於一般備註解的引數的轉化例如@Body標識的物件做一些操作
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      // 返回retrofit物件
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

相關參考連結

Retrofit2 完全解析 探索與okhttp之間的關係
別人家SDK中的設計模式--Android Retrofit庫原始碼解讀
Retrofit分析-漂亮的解耦套路
獨特的架構方式,Retrofit原始碼簡析。

相關文章