通俗易懂系列 | 設計模式(八):建造者模式

介紹

今天咱們將研究java中的Builder模式。Builder 設計模式是一種創造性的設計模式,如工廠模式和抽象工廠模式。
當Object包含許多屬性時,引入了Builder模式來解決Factory和Abstract Factory設計模式的一些問題。
當Object包含許多屬性時,Factory和Abstract Factory設計模式存在三個主要問題。java

  1. 從客戶端程序傳遞到Factory類的參數太多,可能容易出錯,由於大多數狀況下,參數的類型是相同的,而從客戶端來講,很難維護參數的順序。
  2. 一些參數多是可選的,但在Factory模式中,咱們被迫發送全部須要發送爲NULL的參數和可選參數。
  3. 若是對象很重而且它的建立很複雜,那麼全部這些複雜性都將成爲Factory類的一部分,使人困惑。

咱們能夠經過提供具備所需參數的構造函數而後使用不一樣的setter方法來設置可選參數來解決大量參數的問題。這種方法的問題是,除非明確設置全部屬性,不然Object狀態將不一致。git

Builder模式經過提供逐步構建對象的方法並提供實際返回最終Object的方法,解決了大量可選參數和不一致狀態的問題。github

意圖

將複雜對象的構造與其表示分開,以便相同的構造過程能夠建立不一樣的表示。算法

定義

現實世界的例子設計模式

想象一下角色扮演遊戲的角色生成器。最簡單的選擇是讓計算機爲您建立角色。可是若是你想選擇職業,性別,頭髮顏色等角色細節,那麼角色生成將成爲一個按部就班的過程,在全部選擇準備就緒時完成。app

簡單來講函數

容許您建立不一樣風格的對象,同時避免構造函數被污染。當有幾種不一樣的構造函數時頗有用。或者在建立對象時涉及不少步驟。ui

維基百科說this

構建器模式是對象建立軟件設計模式,其目的是找到伸縮構造器反模式的解決方案。翻譯

話雖如此,讓我補充說一下伸縮構造器反模式是什麼。某時某刻,咱們都會看到以下構造函數:

public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {
}

正如您所看到的,構造函數參數的數量很快就會失控,而且可能很難理解參數的排列。此外,若是您但願未來添加更多選項,此參數列表可能會繼續增加。這就被稱爲"the telescoping constructor anti-pattern"(可伸縮構造器的反模式)。

理智的替代方案是使用Builder模式。

實例

讓咱們看看如何在java中實現構建器設計模式。

  1. 首先,您須要建立一個靜態嵌套類,而後將全部參數從外部類複製到Builder類。咱們應該遵循命名約定,若是類名是Computer那麼構建器類應該命名爲ComputerBuilder。
  2. Java Builder類應該有一個公共構造函數,其中包含全部必需的屬性做爲參數。
  3. Java Builder類應具備設置可選參數的方法,而且應在設置可選屬性後返回相同的Builder對象。
  4. 最後一步是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)

總結

優勢: 一、建造者獨立,易擴展。 二、便於控制細節風險。
缺點: 一、產品必須有共同點,範圍有限制。 二、如內部變化複雜,會有不少的建造類。
注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。

這就是java中的構建器設計模式的所有內容。
翻譯於:builder-design-pattern-in-java
參考:java-design-patterns

相關文章
相關標籤/搜索