一起學設計模式 - 建造者模式

建造者模式(Builder Pattern)屬於創建型模式的一種,將多個簡單對象構建成一個複雜的對象,構建過程抽象化,不同實現方法可以構造出不同表現(屬性)的對象,還提供了一種更加優雅構建對象的方式…

概述

有時候構建一個複雜的對象,需要經過好幾步的處理,比如常用的StringBuffer、StringBuilder、以及Swagger(一種接口文檔),都是以這種模式構建對象的

優點

  • 建造者模式比較獨立,將對象本身與構建過程解耦
  • 精準控制構建出的對象和內容,構造層和顯示層是分離的
  • 寫法上更加優雅

缺點

  • 範圍受限,不適合差異較大的對象
  • 內部複雜多變,構造類相對會多

適用場景

  • 構建具有共同特性的複雜對象

相關模式

抽象工廠模式與建造者模式相似,因爲它也可以創建複雜對象。主要的區別是建造者模式着重於一步步得構造出複雜對象。而抽象工廠模式着重於多個系列的產品對象(簡單的或是複雜的)。建造者是在最後的一步返回對象,而對於抽象工廠來說,對象是立即返回的。

案例

傳統方式

public class Summoner {

    private String name;
    private String type;
    private String innate;

    public Summoner(String name, String type, String innate) {
        this.name = name;
        this.type = type;
        this.innate = innate;
    }
}

簡單的對象我們可以使用下面這種方式,因爲屬性較少這種方式還看的,但不幸的是如果要增加字段或我們還需要去擴展構造方法,且可讀性不好,相同類型的情況下在一定程度上混淆視聽了

Summoner s1 = new Summoner("德瑪","戰士","戰爭雷霆");

爲什麼不調用無參數的構造函數,通過setter方法來減輕問題。

解答: 如果程序員忘記調用一個特定的setter方法會發生什麼?我們可能得到的是一個部分初始化的對象,而且編譯器也不會檢測出任何問題。

  • 構造函數參數太多
  • 錯誤的對象狀態

使用模式

在我們的示例中,改造下召喚師類

public class Summoner {

    private String name;
    private String type;
    private String innate;

    private Summoner(Builder builder) {
        this.name = builder.name;
        this.type = builder.type;
        this.innate = builder.innate;
    }

    protected static class Builder {
        private String name;
        private String type;
        private String innate;

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

        protected Builder type(String type) {
            this.type = type;
            return this;
        }

        protected Builder innate(String innate) {
            this.innate = innate;
            return this;
        }
        protected Summoner build() {
            return new Summoner(this);
        }
    }
}

public class BuilderDemo {

    public static void main(String[] args) {
        Summoner monkey = new Summoner.Builder().name("齊天大聖 - 孫悟空").type("上單 - AD").innate("基石天賦 - 戰爭雷霆").build();
        System.out.println(monkey.toString());

        Summoner mouse = new Summoner.Builder().name("瘟疫之源 - 圖奇").type("下路 - ADC").innate("基石天賦 - 戰陣熱誠").build();
        System.out.println(mouse.toString());

        Summoner diann = new Summoner.Builder().name("皎月女神 - 戴安娜").type("中單 - AP").build();
        System.out.println(diann.toString());
    }
}

建造者模式讓我們寫的代碼更具可讀性,可理解爲建立複雜的物體。它往往是實現一個連貫的操作,從而更加直觀,此處由於類型較爲單一差距不大,但遇到複雜對象構建差距就立竿見影了

Summoner{name='齊天大聖 - 孫悟空', type='上單 - AD', innate='基石天賦 - 戰爭雷霆'}
Summoner{name='瘟疫之源 - 圖奇', type='下路 - ADC', innate='基石天賦 - 戰陣熱誠'}
Summoner{name='皎月女神 - 戴安娜', type='中單 - AP', innate='null'}

總結

我們通過一個簡單的代碼例子開始,慢慢變得複雜。然後使用Builder模式來解決我們發現的問題。

如果你發現自己在一個情況下,你不斷添加新參數的構造函數,使得代碼變得容易出錯,很難讀,也許可以考慮使用一個Builder重構你的代碼。

推薦

- 說點什麼

全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter4/battcn-builder

  • 個人QQ:1837307557
  • battcn開源羣(適合新手):391619659

微信公衆號:battcn(歡迎調戲)

發佈了60 篇原創文章 · 獲贊 19 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章