當對象構建過程極其複雜(如需分步驟、引入參數、不同表示)時,建造者模式 能將「構建邏輯」與「具體表示」解耦,讓相同構建流程產出不同產品。本文以「大學四年教育」為生活類比,配合 UML、完整代碼與對比工廠模式,徹底講透 Builder。

核心關係:
Director 聚合 Builder*,透過多態呼叫 BuildPartA/B/C。Construct() 封裝固定構建順序。ConcreteBuilder 實現具體構建細節,持有 Product* 並最終 GetProduct()。class Product {
string m_partA, m_partB, m_partC;
public:
void setPartA(const string& s) { m_partA = s; }
void setPartB(const string& s) { m_partB = s; }
void setPartC(const string& s) { m_partC = s; }
};
class Builder {
public:
virtual void BuildPartA() = 0;
virtual void BuildPartB() = 0;
virtual void BuildPartC() = 0;
virtual Product* GetProduct() = 0;
virtual ~Builder() {}
};
class ConcreteBuilder1 : public Builder { /* 實現細節1 */ };
class ConcreteBuilder2 : public Builder { /* 實現細節2 */ };
class Director {
Builder* m_pBuilder;
public:
Director(Builder* b) : m_pBuilder(b) {}
void Construct() { // 固定構建順序
m_pBuilder->BuildPartA();
m_pBuilder->BuildPartB();
m_pBuilder->BuildPartC();
}
~Director() { delete m_pBuilder; }
};
ConcreteBuilder1::ConcreteBuilder1() {
m_pProduct = new Product();
cout << "Create empty product!" << endl;
}
void ConcreteBuilder1::BuildPartA() { m_pProduct->setPartA("A"); cout << "BuildPartA" << endl; }
void ConcreteBuilder1::BuildPartB() { m_pProduct->setPartB("B"); cout << "BuildPartB" << endl; }
void ConcreteBuilder1::BuildPartC() { m_pProduct->setPartC("C"); cout << "BuildPartC" << endl; }
Product* ConcreteBuilder1::GetProduct() { return m_pProduct; }
int main() {
Director* d1 = new Director(new ConcreteBuilder1());
d1->Construct(); // 輸出: Create empty product! BuildPartA BuildPartB BuildPartC
Director* d2 = new Director(new ConcreteBuilder2());
d2->Construct(); // 同樣流程,但細節不同
return 0;
}
| 維度 | Builder 模式 | Factory 模式 |
|---|---|---|
| 關注點 | 構建順序與細節 | 創建對象本身 |
| 適用場景 | 產品複雜、多步驟、參數化、不同表示 | 產品相對簡單、一次性創建 |
| 返回時機 | 構建完成後 GetProduct() | 創建即返回 |
| 耦合度 | Director 僅依賴 Builder 介面 | Client 直接依賴 Factory |
class HtmlBuilder {
HtmlElement root;
public:
HtmlBuilder(string name) : root(name) {}
HtmlBuilder& addChild(string name, string text) {
root.elements.emplace_back(name, text);
return *this; // 支援鏈式
}
string str() { return root.str(); }
};
// 使用
HtmlBuilder builder("ul");
builder.addChild("li", "Item1").addChild("li", "Item2");
cout << builder.str();
這是 Builder 在現代 C++(如 std::optional、std::variant、Builder Pattern for Protobuf)中的常見演進形式。