天天看點

從RequestConfig源碼學Bulider設計模型

讀代碼,發現有這樣一個寫法

//設定請求的逾時時間
RequestConfig rconfig = RequestConfig.custom().setConnectTimeout((int)waitTime).setSocketTimeout((int)waitTime).build();
           

之前在看lombok的時候,學到了鍊式調用。但是Builder模式隻聽過,并不知道啥意思,正好梳理一下。

Builder模式解決的問題:

在以前寫代碼的時候,對于實體類都是寫構造方法,并提供get、set方法,一般的實體類屬性很少,倒還好沒感覺有啥不舒服,但是當屬性過多的時候,調用就很麻煩,一個個屬性去對比傳參,很容易就寫錯位置了。

對于這個問題,看别的文章說可以設定空參構造方法,并提供get、set方法,調用的時候直接new一個對象,通過對象.setxxx()來使用,但是會存在對象不一緻的問題。

解決的辦法肯定就是Builder模型了,下面結合RequestConfig中的代碼來認識Builder模式。

首先,RequestConfig的所有屬性值都是final修飾的,表明Requestconfig對象是不可變的。

public static final RequestConfig DEFAULT = new Builder().build();

    private final boolean expectContinueEnabled;
    private final HttpHost proxy;
    private final InetAddress localAddress;
    private final boolean staleConnectionCheckEnabled;
    private final String cookieSpec;
    private final boolean redirectsEnabled;
    private final boolean relativeRedirectsAllowed;
    private final boolean circularRedirectsAllowed;
    private final int maxRedirects;
    private final boolean authenticationEnabled;
    private final Collection<String> targetPreferredAuthSchemes;
    private final Collection<String> proxyPreferredAuthSchemes;
    private final int connectionRequestTimeout;
    private final int connectTimeout;
    private final int socketTimeout;
    private final boolean contentCompressionEnabled;
           

然後預設構造方法是私有的,意味着調用者不能直接建立對象。同時源碼中對屬性僅提供get方法。

RequestConfig(
            final boolean expectContinueEnabled,
            final HttpHost proxy,
            final InetAddress localAddress,
            final boolean staleConnectionCheckEnabled,
            final String cookieSpec,
            final boolean redirectsEnabled,
            final boolean relativeRedirectsAllowed,
            final boolean circularRedirectsAllowed,
            final int maxRedirects,
            final boolean authenticationEnabled,
            final Collection<String> targetPreferredAuthSchemes,
            final Collection<String> proxyPreferredAuthSchemes,
            final int connectionRequestTimeout,
            final int connectTimeout,
            final int socketTimeout,
            final boolean contentCompressionEnabled) {
        super();
        this.expectContinueEnabled = expectContinueEnabled;
        this.proxy = proxy;
        this.localAddress = localAddress;
        this.staleConnectionCheckEnabled = staleConnectionCheckEnabled;
        this.cookieSpec = cookieSpec;
        this.redirectsEnabled = redirectsEnabled;
        this.relativeRedirectsAllowed = relativeRedirectsAllowed;
        this.circularRedirectsAllowed = circularRedirectsAllowed;
        this.maxRedirects = maxRedirects;
        this.authenticationEnabled = authenticationEnabled;
        this.targetPreferredAuthSchemes = targetPreferredAuthSchemes;
        this.proxyPreferredAuthSchemes = proxyPreferredAuthSchemes;
        this.connectionRequestTimeout = connectionRequestTimeout;
        this.connectTimeout = connectTimeout;
        this.socketTimeout = socketTimeout;
        this.contentCompressionEnabled = contentCompressionEnabled;
    }
           

在類中定義了一個内部類Builder,提供了私有構造方法Bulider(),并對必要屬性進行初始指派。通過set方法指派,并傳回Builder自身

public static class Builder {

        private boolean expectContinueEnabled;
        private HttpHost proxy;
        private InetAddress localAddress;
        private boolean staleConnectionCheckEnabled;
        private String cookieSpec;
        private boolean redirectsEnabled;
        private boolean relativeRedirectsAllowed;
        private boolean circularRedirectsAllowed;
        private int maxRedirects;
        private boolean authenticationEnabled;
        private Collection<String> targetPreferredAuthSchemes;
        private Collection<String> proxyPreferredAuthSchemes;
        private int connectionRequestTimeout;
        private int connectTimeout;
        private int socketTimeout;
        private boolean contentCompressionEnabled;

        Builder() {
            super();
            this.staleConnectionCheckEnabled = false;
            this.redirectsEnabled = true;
            this.maxRedirects = 50;
            this.relativeRedirectsAllowed = true;
            this.authenticationEnabled = true;
            this.connectionRequestTimeout = -1;
            this.connectTimeout = -1;
            this.socketTimeout = -1;
            this.contentCompressionEnabled = true;
        }
           

在内部類中定義了一個Builder()方法,并把Builder對象傳入RequsetConfig私有構造函數中,并傳回RequestConfig對象。

public RequestConfig build() {
            return new RequestConfig(
                    expectContinueEnabled,
                    proxy,
                    localAddress,
                    staleConnectionCheckEnabled,
                    cookieSpec,
                    redirectsEnabled,
                    relativeRedirectsAllowed,
                    circularRedirectsAllowed,
                    maxRedirects,
                    authenticationEnabled,
                    targetPreferredAuthSchemes,
                    proxyPreferredAuthSchemes,
                    connectionRequestTimeout,
                    connectTimeout,
                    socketTimeout,
                    contentCompressionEnabled);
        }
           

另外Requsetconfig提供了一個靜态方法custom(),因為Builder構造方法是私有的。

//本文最開始的RequestConfig.custom()
//就是調用的以下方法
public static RequestConfig.Builder custom() {
        return new Builder();
    }

           

可以用三句話來表示Builder模式的使用方法:

1.得到待建立對象的Builder對象 ,這是通過RequestConfig.custom()

2.通過Builder對象一步一步建構待建立對象 

3.通過build()方法真正建立對象并傳回 

總結:

1、對于Builder來說,包含了三部分:

       final成員變量

       私有構造器

       靜态内部類

final成員變量保證了初始化安全性,即在構造器執行完成之前必須顯示對成員變量初始化。這裡是在構造函數中傳入Builder來對其初始化。

2、構造器為什麼要聲明為私有的?保證了外部建立執行個體時隻能通過靜态内部類的build()方法來實作。

3、為什麼是靜态内部類?因為構造器是私有的,導緻外部隻能通過内部類的build()方法來實作。而非靜态内部類對象的建立又依賴于外部類對象,即必須有外部類對象來建立(外部類對象.new InnerClassName()),這樣就陷入了死循環。而靜态内部類不需要依賴于外部類對象,隻需要通過 “new OutClassName.InnerClassName()”就可以完成執行個體化。

4、内部類Builder通過final關鍵字來區分必需參數和非必需參數。通過builder()方法完成外部類執行個體化。這裡利用内部類可以通路外部私有元素的特性。

5、總的來看,就是外部類通過靜态内部類完成了自己成員變量的初始化。

總結引用自:https://www.cnblogs.com/uodut/p/7070424.html