Java中設計模式(八):建造者模式
介紹
今天我們將研究java中的Builder模式。Builder 設計模式是一種創造性的設計模式,如工廠模式和抽象工廠模式。
當Object包含許多屬性時,引入了Builder模式來解決Factory和Abstract Factory設計模式的一些問題。
當Object包含許多屬性時,Factory和Abstract Factory設計模式存在三個主要問題。
- 從客戶端程式傳遞到Factory類的引數太多,可能容易出錯,因為大多數情況下,引數的型別是相同的,而從客戶端來說,很難維護引數的順序。
- 一些引數可能是可選的,但在Factory模式中,我們被迫傳送所有需要傳送為NULL的引數和可選引數。
- 如果物件很重並且它的建立很複雜,那麼所有這些複雜性都將成為Factory類的一部分,令人困惑。
我們可以通過提供具有所需引數的建構函式然後使用不同的setter方法來設定可選引數來解決大量引數的問題。這種方法的問題是,除非明確設定所有屬性,否則Object狀態將不一致。
Builder模式通過提供逐步構建物件的方法並提供實際返回最終Object的方法,解決了大量可選引數和不一致狀態的問題。
意圖
將複雜物件的構造與其表示分開,以便相同的構造過程可以建立不同的表示。
定義
現實世界的例子
想象一下角色扮演遊戲的角色生成器。最簡單的選擇是讓計算機為您建立角色。但是如果你想選擇職業,性別,頭髮顏色等角色細節,那麼角色生成將成為一個循序漸進的過程,在所有選擇準備就緒時完成。
簡單來說
允許您建立不同風格的物件,同時避免建構函式被汙染。當有幾種不同的建構函式時很有用。或者在建立物件時涉及很多步驟。
維基百科說
構建器模式是物件建立軟體設計模式,其目的是找到伸縮構造器反模式的解決方案。
話雖如此,讓我補充說一下伸縮構造器反模式是什麼。某時某刻,我們都會看到如下建構函式:
public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) { }
正如您所看到的,建構函式引數的數量很快就會失控,並且可能很難理解引數的排列。此外,如果您希望將來新增更多選項,此引數列表可能會繼續增長。這就被稱為"the telescoping constructor anti-pattern"(可伸縮構造器的反模式)。
理智的替代方案是使用Builder模式。
例項
讓我們看看如何在java中實現構建器設計模式。
- 首先,您需要建立一個靜態巢狀類,然後將所有引數從外部類複製到Builder類。我們應該遵循命名約定,如果類名是Computer那麼構建器類應該命名為ComputerBuilder。
- Java Builder類應該有一個公共建構函式,其中包含所有必需的屬性作為引數。
- Java Builder類應具有設定可選引數的方法,並且應在設定可選屬性後返回相同的Builder物件。
- 最後一步是build()在構建器類中提供一個方法,該方法將返回客戶端程式所需的Object。為此,我們需要在Class中使用Builder類作為引數的私有建構函式。
下面是示例構建器模式示例程式碼,首先,我們有我們想要創造的英雄
public final class Hero { private final Profession profession; private final String name; private final HairType hairType; private final HairColor hairColor; private final Armor armor; private final Weapon weapon; private Hero(Builder builder) { this.profession = builder.profession; this.name = builder.name; this.hairColor = builder.hairColor; this.hairType = builder.hairType; this.weapon = builder.weapon; this.armor = builder.armor; } }
然後我們有了建設者
public static class HeroBuilder { private final Profession profession; private final String name; private HairType hairType; private HairColor hairColor; private Armor armor; private Weapon weapon; public Builder(Profession profession, String name) { if (profession == null || name == null) { throw new IllegalArgumentException("profession and name can not be null"); } this.profession = profession; this.name = name; } public Builder withHairType(HairType hairType) { this.hairType = hairType; return this; } public Builder withHairColor(HairColor hairColor) { this.hairColor = hairColor; return this; } public Builder withArmor(Armor armor) { this.armor = armor; return this; } public Builder withWeapon(Weapon weapon) { this.weapon = weapon; return this; } public Hero build() { return new Hero(this); } }
請注意,Hero類只有getter方法,沒有公共建構函式。因此,獲取Hero物件的唯一方法是通過HeroBuilder類。
然後它可以用作如下,顯示如何使用Builder類來獲取物件:
Hero mage = new Hero.HeroBuilder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();
使用場景
使用Builder模式時
- 用於建立複雜物件的演算法應該獨立於構成物件的部分以及它們如何組裝
- 構造過程必須允許對構造的物件進行不同的表示
JDK中的Builder設計模式示例
Java類中的一些構建器模式示例是;
- java.lang.StringBuilder#append()(未同步)
- java.lang.StringBuffer#append()(synchronized)
總結
優點: 1、建造者獨立,易擴充套件。 2、便於控制細節風險。
缺點: 1、產品必須有共同點,範圍有限制。 2、如內部變化複雜,會有很多的建造類。
注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。
這就是java中的構建器設計模式的全部內容。
翻譯於:ofollow,noindex" target="_blank">builder-design-pattern-in-java