建造者模式(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
重構你的代碼。
推薦
- lombok: https://github.com/rzwitserloot/lombok
- IntelliJ IDEA : InnerBuilder 插件
- 說點什麼
全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter4/battcn-builder
- 個人QQ:1837307557
- battcn開源羣(適合新手):391619659
微信公衆號:battcn
(歡迎調戲)