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

建造者模式:將複雜對象構建與表示分離,支援多種表示輸出

     編輯:關於C語言

模式動機

當一個物件的構建過程極其複雜(步驟多、順序敏感、參數組合爆炸),且需要根據不同需求產出不同「表示」(如:同樣「組裝電腦」流程,可產出「辦公機」、「遊戲機」、「伺服器」三種配置),建造者模式將構建算法與具體部件組裝解耦,實現「一套流程、多種產品」。

結構角色

角色職責
Product最終產生的複雜物件(如 `Computer`)
Builder (Abstract)定義構建步驟介面(`buildCPU()`、`buildRAM()`、`buildStorage()`、`getResult()`)
ConcreteBuilder實作具體部件組裝邏輯,維護半成品狀態(`GamingComputerBuilder`、`OfficeComputerBuilder`)
Director封裝構建順序,呼叫 Builder 步驟,對客戶端隱藏細節
Client建立 ConcreteBuilder → 注入 Director → 呼叫 `construct()` → 取得 Product

經典案例:把大象裝冰箱(C# 實作)

// 產品:冰箱內容物清單
class FridgeContent {
    public List Items { get; } = new List();
    public override string ToString() => string.Join(" → ", Items);
}

// 抽象建造者:固定「開門 → 放入 → 關門」三步驟
abstract class PutIntoFridgeBuilder {
    protected FridgeContent Content = new FridgeContent();
    public abstract void OpenFridge();
    public abstract void PutInto();
    public abstract void CloseFridge();
    public FridgeContent GetResult() => Content;
}

// 具體建造者:大象版
class ElephantBuilder : PutIntoFridgeBuilder {
    private readonly string _name;
    public ElephantBuilder(string name) => _name = name;
    public override void OpenFridge() => Content.Items.Add("打開冰箱門");
    public override void PutInto() => Content.Items.Add($"把 {_name} 裝進冰箱");
    public override void CloseFridge() => Content.Items.Add("關上冰箱門");
}

// 具體建造者:過期牛奶版
class ExpiredMilkBuilder : PutIntoFridgeBuilder {
    public override void OpenFridge() => Content.Items.Add("打開冰箱門");
    public override void PutInto() => Content.Items.Add("放入過期牛奶");
    public override void CloseFridge() => Content.Items.Add("關上冰箱門");
}

// 指揮者:統一流程
class Director {
    private readonly PutIntoFridgeBuilder _builder;
    public Director(PutIntoFridgeBuilder builder) => _builder = builder;
    public void Construct() {
        _builder.OpenFridge();
        _builder.PutInto();
        _builder.CloseFridge();
    }
}

// 客戶端
class Program {
    static void Main() {
        var elephant = new ElephantBuilder("小象");
        var director = new Director(elephant);
        director.Construct();
        Console.WriteLine(elephant.GetResult());

        var milk = new ExpiredMilkBuilder();
        director = new Director(milk);
        director.Construct();
        Console.WriteLine(milk.GetResult());
    }
}

輸出結果

打開冰箱門 → 把 小象 裝進冰箱 → 關上冰箱門
打開冰箱門 → 放入過期牛奶 → 關上冰箱門

進階變體:流暢介面 Builder (Fluent Builder)

現代 C#/Java 常省略 Director,改用鏈式呼叫:

public class ComputerBuilder {
    private string cpu, ram, storage, gpu;
    public ComputerBuilder CPU(string v) { cpu = v; return this; }
    public ComputerBuilder RAM(string v) { ram = v; return this; }
    public ComputerBuilder Storage(string v) { storage = v; return this; }
    public ComputerBuilder GPU(string v) { gpu = v; return this; }
    public Computer Build() => new Computer(cpu, ram, storage, gpu);
}

// 使用
var pc = new ComputerBuilder()
    .CPU("i9-13900K")
    .RAM("64GB DDR5")
    .Storage("2TB NVMe")
    .GPU("RTX 4090")
    .Build();

模式對比:建造者 vs 工廠 vs 原型

維度BuilderAbstract FactoryPrototype
核心意圖分步構建複雜物件創建相關物件族群複製現有實例
構建過程多步驟、有序單步驟、即時零步驟、克隆
適用場景參數多、順序敏感、多表示產品族固定、等級固定創建成本高、狀態少變

最佳實踐清單

  1. 必要時才用:參數 < 4、構建單一、無多表示 → 直接用構造函式/工廠方法。
  2. 不可變物件:Builder 累積狀態,`Build()` 產出 `readonly`/`final` 物件,保證執行緒安全。
  3. 驗證前置:`Build()` 內集中檢查必要欄位、互斥約束,拋出具體異常。
  4. 避免 Director 過度設計:流程固定且單一時,Client 直接鏈式呼叫 Builder 即可。
  5. 配合依賴注入:將 `IBuilder` 註冊為 Scoped/Transient,Controller 注入即用。

建造者模式是「複雜構建邏輯」的封裝器。記住:構建過程固定、表示多變 → Builder;產品族固定、等級固定 → Abstract Factory;複製比構建快 → Prototype。

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