天天看點

設計模式-建立者模式總結

建立者模式的特點及使用場景

《Effective Java》—— 建立與銷毀對象 一章中有寫道:當一個類中有大量的構造參數時,靜态方法和構造器已經不能滿足對象的執行個體化,那麼我們将考慮建構器。

建構器模式:

  • 1、重疊構造器模式
  • 2、javaBeans模式(自己常用的一種)
  • 3、builder模式

說明:

  • 重疊構造器模式:這種模式下,提供第一個隻有必要參數的構造器,第二個構造器有一個可選參數,第三個有兩個可選參數,以此類推,最後一個構造器包含所有可選參數。
  • javaBeans模式:調用在各分無參構造器建立對象,然後調用setter方法來設定每個必要的參數,以及每個相關的可選參數。
  • builder模式:builder像個構造器一樣,可以對其參數強加限制條件。build方法可以檢驗這些限制條件。将參數從builder拷貝到對象中之後,并在對象域而不是builder域中對它們進行檢驗,這一點很重要。如果違反了人格限制條件,build方法就應該抛出IllegalStateException。異常的詳細資訊應該顯示出違反哪個限制條件。

從上不難看出:

  • 重疊構造器模式在參數很多的情況下,用戶端代碼會很難寫,并且難以閱讀。
  • javaBeans模式因為構造過程分到了幾個調用中,在構造過程中javaBean可能處于不一緻的狀态,類無法僅僅通過校驗構造參數的* 有效性來保證一緻性。這樣程式員需要付出額外的努力來確定它的線程安全
  • builder模式技能保證像重疊構造器模式那樣的安全性,也能保證像javaBeans模式那麼好的可讀性。
builder模式十分靈活,可以利用單個builder建構多個對象。builder的參數可以在建立對象期間進行調整,也可以随着不同的對象而改變。

代碼示例

class DefaultHttpClientFactory {
    private static PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    private static RequestConfig defaultRequestConfig = RequestConfig.custom().build();

    private static int mgrMaxTotal = DEFAULT_MAX_TOTAL;  //全局最大連接配接數
    private static int mgrDefaultMaxPerRoute = DEFAULT_MAX_PER_ROUTE; //每個主機最大連接配接數
    private static int connReqTimeout = DEFAULT_CONN_REQ_TIMEOUT;   //從連接配接池擷取連接配接逾時時間
    private static int connTimout = DEFAULT_CONN_TIMEOUT;   //發起連接配接逾時時間
    private static int connSocketTimeout = DEFAULT_CONN_SOCKET_TIMEOUT;    //連接配接套接字等待時間

    public static class Builder {
        private int mgrMaxTotal = DEFAULT_MAX_TOTAL;  //全局最大連接配接數
        private int mgrDefaultMaxPerRoute = DEFAULT_MAX_PER_ROUTE; //每個主機最大連接配接數
        private int connReqTimeout = DEFAULT_CONN_REQ_TIMEOUT;   //從連接配接池擷取連接配接逾時時間
        private int connTimout = DEFAULT_CONN_TIMEOUT;   //發起連接配接逾時時間
        private int connSocketTimeout = DEFAULT_CONN_SOCKET_TIMEOUT;    //連接配接套接字等待時間

        Builder() {
        }

        public Builder maxTotal(int maxTotal) {
            this.mgrMaxTotal = maxTotal;
            return this;
        }

        public Builder maxPerRoute(int maxPerRoute) {
            this.mgrDefaultMaxPerRoute = maxPerRoute;
            return this;
        }

        public Builder connReqTimeout(int connReqTimeout) {
            this.connReqTimeout = connReqTimeout;
            return this;
        }

        public Builder connTimout(int connTimout) {
            this.connTimout = connTimout;
            return this;
        }

        public Builder connSocketTimeout(int connSocketTimeout) {
            this.connSocketTimeout = connSocketTimeout;
            return this;
        }

        public DefaultHttpClientFactory build() {
            return new DefaultHttpClientFactory(this);
        }
    }

    private DefaultHttpClientFactory(Builder builder) {
        mgrMaxTotal = builder.mgrMaxTotal;
        mgrDefaultMaxPerRoute = builder.mgrDefaultMaxPerRoute;
        connReqTimeout = builder.connReqTimeout;
        connTimout = builder.connTimout;
        connSocketTimeout = builder.connSocketTimeout;
    }

    public static DefaultHttpClientFactory.Builder custom() {
        return new DefaultHttpClientFactory.Builder();
    }

    public CloseableHttpClient getClient() {
        cm.setMaxTotal(mgrMaxTotal); // 設定最大連接配接數
        cm.setDefaultMaxPerRoute(mgrDefaultMaxPerRoute); // 設定每個路由最大連接配接數,每個獨立的host為1個路由
        RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
                .setConnectionRequestTimeout(connReqTimeout)//從連接配接池擷取連接配接逾時時間
                .setConnectTimeout(connTimout)//發起連接配接逾時時間
                .setSocketTimeout(connSocketTimeout)//連接配接套接字等待時間
                .setRedirectsEnabled(false)
                .build();

        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setConnectionManager(cm);
        httpClientBuilder.setDefaultRequestConfig(requestConfig);

        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)); // 去掉預設的3次重試
        CloseableHttpClient httpClient = httpClientBuilder.build();
        return httpClient;
    }
}
           

歡迎關注

高廣超的簡書部落格

與 收藏文章 !

頭條号:網際網路技術棧

個人介紹:

** 高廣超** :多年一線網際網路研發與架構設計經驗,擅長設計與落地高可用、高性能網際網路架構。目前就職于美團網,負責核心業務研發工作。

本文首發在

轉載請注明!

設計模式-建立者模式總結

image.png