設計模式筆記-建造者(Builder)

目的

將複雜對象的構建表示分離,達到同樣構建過程能夠得到不同的表示。

說明

現實例子

角色扮演遊戲中的角色構建,通過選擇職業、性別、髮型等屬性構建自己的角色,構建過程一致,卻得到不同的角色。

講人話

允許你在不污染構造方法的前提下,構建一個類的不同風格的實例。

維基百科

建造者模式是爲解決可伸縮構造器反模式(telescoping constructor anti-patter)的一種對象創建型軟件設計模式

構造器反模式,某一時間點我們有如下的一個構造器

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

如上所示,構造器的參數很多且很難理解參數的排列順序。當需要添加屬性時,參數還會繼續增長。

編程樣例

手工打造

通過手寫代碼方式實現建造者模式

  • 實體類+建造者類
package design.creational.builder;

/**
 * 角色類
 *
 * @author faith.huan 2019-11-28 21:45
 */
public class Hero {

    /**
     * 暱稱
     */
    private String name;

    /**
     * 種族
     */
    private String race;
    /**
     * 職業
     */
    private String profession;

    /**
     * 髮型
     */
    private String hairType;

    /**
     * 髮色
     */
    private String hairColor;

    /**
     * 膚色
     */
    private String skinColor;

    public Hero(HeroBuilder builder) {
        this.name = builder.name;
        this.race = builder.race;
        this.profession = builder.profession;
        this.hairType = builder.hairType;
        this.hairColor = builder.hairColor;
        this.skinColor = builder.skinColor;
    }

    /**
     * 得到建造者HeroBuilder
     */
    public static HeroBuilder builder() {
        return new HeroBuilder();
    }

    @Override
    public String toString() {
        return "Hero{" +
                "name='" + name + '\'' +
                ", race='" + race + '\'' +
                ", profession='" + profession + '\'' +
                ", hairType='" + hairType + '\'' +
                ", hairColor='" + hairColor + '\'' +
                ", skinColor='" + skinColor + '\'' +
                '}';
    }

    /**
     * 建造者類
     */
    public static class HeroBuilder {

        private String name;
        private String race;
        private String profession;
        private String hairType;
        private String hairColor;
        private String skinColor;

        public HeroBuilder withName(String name) {
            this.name = name;
            return this;
        }

        public HeroBuilder withRace(String race) {
            this.race = race;
            return this;
        }

        public HeroBuilder withProfession(String profession) {
            this.profession = profession;
            return this;
        }

        public HeroBuilder withHairType(String hairType) {
            this.hairType = hairType;
            return this;
        }

        public HeroBuilder withHairColor(String hairColor) {
            this.hairColor = hairColor;
            return this;
        }

        public HeroBuilder withSkinColor(String skinColor) {
            this.skinColor = skinColor;
            return this;
        }

        public Hero build() {
            return new Hero(this);
        }

    }
}

  • 測試類
package design.creational.builder;

/**
 * 角色類測試
 *
 * @author faith.huan 2019-11-28 22:05:22
 */
public class HeroTest {

    public static void main(String[] args) {

        Hero hero = Hero.builder().withName("夕日之殤")
                .withRace("人族")
                .withProfession("青雲門")
                .withHairType("飄逸髮型")
                .withHairColor("深空灰")
                .withSkinColor("亮銀色")
                .build();

        System.out.println(hero);
    }
}

測試結果
在這裏插入圖片描述

Lombok版本

通過上面手寫建造者模式的例子發現構建過程比較清爽,然而建造者手寫有點複雜,21世紀了還是要藉助下高科技比較好,下面展示如何使用Lombok完成上面的建造者例子

package design.creational.builder;

import lombok.Builder;
import lombok.ToString;

/**
 * 使用Lombok完成建造者示例
 * 
 * @author faith.huan 2019-11-28 22:14:01
 */
@Builder
@ToString
public class HeroLombok {

    /**
     * 暱稱
     */
    private String name;

    /**
     * 種族
     */
    private String race;
    /**
     * 職業
     */
    private String profession;

    /**
     * 髮型
     */
    private String hairType;

    /**
     * 髮色
     */
    private String hairColor;

    /**
     * 膚色
     */
    private String skinColor;
    
}

額…簡單的好像令人髮指,通過5分鐘手寫的建造者代碼,通過Lombok的一個註解@Builder寫完了

  • 測試代碼
package design.creational.builder;

/**
 * 角色類測試
 *
 * @author faith.huan 2019-11-28 22:05:22
 */
public class HeroLombokTest {

    public static void main(String[] args) {

        HeroLombok heroLombok = HeroLombok.builder().name("夕日之殤")
                .race("人族")
                .profession("青雲門")
                .hairType("飄逸髮型")
                .hairColor("深空灰")
                .skinColor("亮銀色")
                .build();

        System.out.println(heroLombok);
    }
}

測試結果
在這裏插入圖片描述
從測試結果看手寫的建造者與Lombok生成的建造者都能完成角色構建。

適用性

  • 創建複雜對象的算法應獨立於組成對象的零件及其組裝方式
  • 構造過程必須允許所構造的對象具有不同的表示形式

真實例子


參考
https://github.com/iluwatar/java-design-patterns/tree/master/builder

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章