天天看點

設計模式(3)—— 建立型——建造者(Builder)

說明

在衆多開源架構或者jdk源碼中常常出現Builder,build相關的類檔案名或者類名,函數名。其中很多如此命名的原因就是因為使用了建造者(Builder)模式。檢視jdk源碼不難發現,我們常用的StringBuilder類也使用了建造者模式。

建造者模式介紹摘要

  • 定義: 将一個複雜對相當建構與它的表示分離,使得同樣的建構過程可以建立不同的表示。
  • 特征. 使用者隻需指定需要建造的類型就可以得到它們,建造過程和細節不需要知道
  • 類型:建立型
  • 适用場景:如果一個對象有非常複雜的内部結構(很多屬性);想把複雜對象的建立和使用分離。
  • 優點:
    • 封裝性好
    • 擴充性好,建造類之間獨立,一定程度上解耦。
  • 缺點:
    • 産生多餘的Builder對象
    • 産品内部發生變化,建造者都要修改,成本較大

代碼實作

場景:我們現在打算入駐網店,是以要送出一份申請資料,申請一個網店店鋪。申請資料送出給業務員(Builder),業務員負責處理相關資料,并将網店的申請結果(Shop類)傳回給申請者。

首先,我們要知道的是具體的建造過程是 由Builder對象完成的。外界直接通過Builder對象來建造擷取一個Shop類的執行個體。具體的UML類圖:

設計模式(3)—— 建立型——建造者(Builder)

這裡我們隻使用一個Shop類,并且在Shop類中有個内部類。用于建立Shop實體類。我們先直接看外部測試代碼,很容易了解:

public class Test {

    public static void main(String[] args) {
    	// 按需,Build相應的屬性覆寫預設的屬性。
    	// build()接在buildXX()屬性之後,直接能夠傳回相應的Shop對象執行個體。
        Shop shop = new Shop.ShopBuilder()
                                    .buildShopName("My Shop Name")
                                    .buildShopDesc("WelCome to my Shop")
                                    .buildShopPhone("13012345678")
                                    .buildShopPhoto("http://xxx.com/i/img.jpg")
                                    .build();
        System.out.println(shop);
    }
}
           

下面是Shop的具體實作類:

public class Shop {

    private String name;
    private String description;
    private String phone;
    private String photo;
	
	// 在Builder類内部,通過 return new Shop(this)直接傳回一個Shop對象。
    public Shop(ShopBuilder shopBuilder){
        this.name = shopBuilder.name;
        this.description = shopBuilder.description;
        this.phone = shopBuilder.phone;
        this.photo = shopBuilder.photo;
    }
	
	//為了友善檢視build結果,我們重寫toString方法。
    @Override
    public String toString() {
        return "Shop{" +
                "name='" + this.name + '\'' +
                ", description='" + this.description + '\'' +
                ", phone='" + this.phone + '\'' +
                ", photo='" + this.photo + '\'' +
                '}';
    }
	
	// 這裡是Builder類,負責Build建造。
	// 注意1:buildXX()屬性,傳回值為本身,這樣友善鍊式操作。
	// 注意2:最後的build()函數,直接build出我們最終想要的實體對象。
    public static class ShopBuilder{
        private String name = "Default name";
        private String description = "Welcome to Default name 's Shop.";
        private String phone = "Default number";
        private String photo = "Default photo";

        public ShopBuilder buildShopName(String name) {
            this.name = name;
            return this;
        }

        public ShopBuilder buildShopDesc(String desc) {
            this.description = desc;
            return this;
        }


        public ShopBuilder buildShopPhone(String phone) {
            this.phone = phone;
            return this;
        }


        public ShopBuilder buildShopPhoto(String photo) {
            this.photo = photo;
            return this;
        }

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

    }
}