總體說來,建造者模式適合于一個具有較多的零件(屬性)的產品(對象)的創建過程。根據產品創建過程中零件的構造是否具有一致的先后順序,可以將其分為如下兩種形式。
一、通過Client、Director、Builder和Product形成的建造者模式
Builder負責Product類對象的具體過程構建,Director負責指導Build,要求Builder按照其指定的順序去完成Produt的構造。最后通過Builder返回建造后的結果。
簡單地說,就好象我要一座房子住,可是我不知道怎么蓋(簡單的砌墻,層次較低),也不知道怎么樣設計(建幾個房間,幾個門好看,層次較高),于是我需要找一幫民工,他們會砌墻,還得找個設計師,他知道怎么設計,我還要確保民工聽設計師的領導,而設計師本身也不干活,光是下命令,這里砌一堵墻,這里砌一扇門,這樣民工開始建設,最后,我可以向民工要房子了。在這個過程中,設計師是什么也沒有,除了他在腦子里的設計和命令,所以要房子也是跟民工要,記住了!
如果我們需要將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示的意圖時,我們可以使用 Builder模式,又叫生成器模式。如果我們用了Builder模式,那么用戶就只需要指定需要建造的類型就可以得到它們,而具體建造的過程和細節就不需要知道了。
比如現在我們有一個這樣的使用場景,需要在屏幕上畫小人,人要有頭手腳,要畫不同的人,胖的小人,瘦的小人,矮的小人。按照通常的寫法,會有很多的樣板代碼,畫人的頭,畫人腳手,如果一不小心,非常容易缺胳膊少腿。
二、通過靜態內部類等方式實現的零件無序話構造:
遇到多個構造器參數時要考慮用構建器。靜態工廠和構造器有個共同的局限性:它們都不能很好地擴展到大量的可選參數。
考慮這樣的一個場景:用一個類表示包裝食品外面顯示的營養成分標簽。這些標簽中有幾個域是必需的:每份的含量、每罐的含量以及每份的卡路里,還有超過20個可選域:總脂肪量、飽和脂肪量、轉化脂肪、膽固醇、鈉等等。
程序員一向習慣采用重疊構造器模式,在這種模式下,你提供第一個只有必要參數的構造器,第二個構造器有一個可選參數,第三個有兩個可選參數,以此類推,最后一個構造器包含所有可選參數。重疊構造器模式可行,但是當有許多參數的時候,客戶端代碼會很難編寫,并且仍然難以閱讀。一長串類型相同的參數會導致一些微妙的錯誤。如果客戶端不小心顛倒了其中兩個參數的順序,編譯器也不會出錯,但是程序在運行時會出現錯誤的行為。
public class Client {
public static void main(String[] args) {
User.Builder builder = new User.Builder();
User user = builder.setName("corn").setAge(100).setAddress("廣州").build();}}
class User {
private String name;
private int age;
private String address;
public String getName() {return name;}
public int getAge() {return age;}
public String getAddress() {return address;}
public static class Builder {
private User user = new User();
public Builder setName(String name) {
user.name = name;return this;}
public Builder setAge(int age) {user.age = age;return this;}
public Builder setAddress(String address) {
user.address = address;return this;}
public User build() {return user;}}}