生成器模式(Builder)

jdon發表於2019-06-17

目的
將複雜物件的構造與其表示分開,以便相同的構造過程可以建立不同的表示。

說明
例如角色扮演遊戲的角色生成器。最簡單的選擇是讓計算機為你建立角色。但是如果你想選擇職業,性別,頭髮顏色等角色細節,那麼角色生成就會逐步完成所有選擇準備就緒的過程。

簡而言之
允許您建立不同風格的物件,同時避免對建構函式造成汙染。當物件有多種風格,或在建立物件時涉及很多步驟時適用。

維基百科說
生成器模式是物件建立軟體設計模式,其目的是找到伸縮構造器反模式的解決方案。
那麼伸縮建構函式反模式是什麼?在某一點上,我們看到了如下的建構函式:
public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) { }
正如您所看到的,建構函式引數的數量很快就會失控,並且可能難以理解引數的排列。此外,如果您希望將來新增更多選項,此引數列表可能會繼續增長。這被稱為伸縮構造器反模式。

原始碼示例
理智的替代方案是使用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 Builder {
    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 mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();


適用場景

  • 建立複雜物件的演算法應獨立於組成物件的部分以及它們的組裝方式
  • 構造過程必須允許對構造的物件進行不同的表示

相關文章