首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 設計模式(4):建造者模式——分步驟構建複雜物件的導演術

     編輯:關於.NET

前言:當「創建」變成「構建」

工廠模式解決「創建什麼」,建造者模式(Builder Pattern)解決「如何一步步構建」。當物件擁有複雜內部結構、多個構成部件、且構建順序固定但部件實作多變時,建造者模式大放異彩:將一個複雜物件的構建與其表示分離,使得相同的構建過程可以創建不同的表示(GoF)。

生活類比:快餐店兒童套餐

  • 產品:兒童套餐(主餐+副餐+飲料+玩具)
  • 建造者:廚房人員(依步驟組裝)
  • 導演者:櫃台人員(知悉套餐構建算法:先主餐、再飲料、最後玩具)
  • 客戶:顧客(選擇 1 號/2 號套餐,不關心組裝細節)

快餐套餐建造者類比

KFC 套餐實戰完整實現

1. 產品類別


public class Food {
    private Hashtable _items = new Hashtable();
    public void Add(string name, string price) => _items.Add(name, price);
    public void Show() {
        Console.WriteLine("Food List:\n------------------------------");
        foreach (DictionaryEntry item in _items) 
            Console.WriteLine($"{item.Key}:\t{item.Value}");
        Console.WriteLine("------------------------------");
    }
}

2. 抽象建造者:定義構建步驟介面


public abstract class Builder {
    public abstract void BuildHamburger();
    public abstract void BuildCoke();
    public abstract void BuildChips();
    public abstract Food GetResult();
}

3. 具體建造者:實作特定風格部件


public class NormalBuilder : Builder {
    private Food _food = new Food();
    public override void BuildHamburger() => _food.Add("NormalHamburger", "¥10.50");
    public override void BuildCoke() => _food.Add("Coke", "¥4.50");
    public override void BuildChips() => _food.Add("Chips", "¥2.00");
    public override Food GetResult() => _food;
}

public class GoldBuilder : Builder {
    private Food _food = new Food();
    public override void BuildHamburger() => _food.Add("GoldHamburger", "¥13.50");
    public override void BuildCoke() => _food.Add("Coke", "¥4.50");
    public override void BuildChips() => _food.Add("Chips", "¥3.50");
    public override Food GetResult() => _food;
}

4. 導演者:封裝固定構建算法


public class FoodManager {
    public void Construct(Builder builder) {
        builder.BuildHamburger(); // 步驟 1
        builder.BuildCoke();      // 步驟 2
        builder.BuildChips();     // 步驟 3(算法固定不變)
    }
}

導演者與建造者交互

5. 客戶端:配置與啟動


public class Client {
    public static void Main() {
        var manager = new FoodManager();
        Console.Write("Enter Food No (1=Normal, 2=Gold): ");
        string no = Console.ReadLine();
        string builderType = ConfigurationManager.AppSettings["No" + no]; // "NormalBuilder" 或 "GoldBuilder"
        
        Builder builder = (Builder)Assembly.Load("KFC").CreateInstance("KFC." + builderType);
        manager.Construct(builder);
        
        Food food = builder.GetResult();
        food.Show();
    }
}

客戶端獲取產品

建造者模式的演化變體

GoF 指出可根據複雜度簡化:

  1. 省略抽象建造者:僅一種具體建造者時,Director 直接依賴 ConcreteBuilder 無抽象建造者
  2. 省略導演者:建造者自身掌控構建順序,Client 直接呼叫 builder.Construct() 無導演者
  3. 合併建造者與產品:部件固定、永不變化時,產品自行構建(如 StringBuilder) 建造者產品合併

另一實戰範例:房屋建造


public interface IHouse {
    bool HasBackyard { get; }
    long RoomCount { get; }
    string Description { get; }
}
public class Apartment : IHouse { /* 無後院、3 房 */ }
public class SingleFamilyHome : IHouse { /* 有後院、5 房 */ }

public class Director {
    public IHouse BuildHouse(bool hasBackyard) 
        => hasBackyard ? new SingleFamilyHome() : new Apartment();
}

此例中導演者直接實例化產品(簡化版建造者),展示「導演者知悉算法、建造者實作細節」的核心分工。

.NET 生態中的建造者身影

  • StringBuilder:最經典的簡化版建造者,Append 系列方法構建字串,ToString() 獲取結果
  • UriBuilder:分步驟設定 Scheme、Host、Port、Path、Query,最後 .Uri 產出
  • DbConnectionStringBuilder:強型別設定連線字串參數,防止注入與拼接錯誤
  • Expression Tree:Expression.Block、Expression.Lambda 等構建邏輯樹
  • ASP.NET Core IApplicationBuilder:UseMiddleware 鏈式構建中介軟體管線
  • Fluent API / Method Chaining:現代 API 設計常用建造者模式實現流暢介面

建造者 vs 抽象工廠 vs 工廠方法

模式關注點核心角色典型場景
工廠方法單一物件創建Factory + Product單一服務實現切換
抽象工廠系列物件創建Factory Family + Product FamilyUI 主題、跨平台 Provider
建造者複雜物件分步構建Director + Builder + Product文檔生成、複雜物件圖、配置物件

關鍵差異:建造者強調「構建過程(算法)」,抽象工廠強調「產品族一致性」,工廠方法強調「單一物件延遲綁定」。

實作要點與最佳實踐

  1. 產品通常無需抽象基類:不同建造者產出的產品差異可能極大(如 XML vs JSON vs PDF),強行抽象反而束縛
  2. 建造者介面方法可為虛擬預設實作:非抽象方法,預設空實作,具體建造者僅覆寫所需步驟
  3. 導演者封裝演算法:構建順序、邏輯判斷(如條件性步驟)集中在 Director,Builder 單純執行
  4. 常與組合模式結合:產品為樹狀結構時,Builder 負責構建節點關係
  5. 流暢介面:現代風格讓 Builder 方法回傳 this,支援鏈式呼叫 builder.SetA().SetB().Build()

適用場景判斷

以下情況適用建造者模式:

  • 產品擁有複雜內部結構(多層巢狀、多組件)
  • 產品屬性間有相依順序(必須先設 A 再設 B)
  • 構建過程需用到外部服務/資源,不宜放入建構子
  • 相同構建算法需產出不同表示(如同一報表資料導出 Excel/PDF/HTML)
  • 不可變物件構建(Builder 累積狀態,Build() 瞬間凍結產出 Immutable 物件)

總結

建造者模式的本質是「解耦構建演算法與部件實作」。導演者知道「做什麼、按什麼順序」,建造者知道「怎麼做具體步驟」,產品只是結果承載者。這種分離讓系統在面對「新增部件類型」、「調整構建順序」、「替換整個產品表示」等變化時,都能從容應對。從 StringBuilder 到 ASP.NET Core 中介軟體管線,建造者模式是構建複雜物件圖的基石藝術。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved