1. 概念
建造者模式是一种创建型设计模式 ,它将一个复杂对象的构建 与表示分离,使得同样的构建过程可以创建不同的表示。
2. 核心角色
- Product(产品):要构建的复杂对象
- Builder(抽象建造者):声明构建产品各部分的方法
- ConcreteBuilder(具体建造者):实现具体构建逻辑,并提供获取产品的方法
- Director(指挥者):定义构建顺序,负责使用Builder接口构建产品
3. 应用场景
适用情况:
- 构造参数多且部分可选(替代多参数构造函数)
- 对象包含多个相同类型的组件(如披萨配料)
- 需要生成不同表示形式的对象(不同配置的电脑)
- 需要控制建造顺序或校验有效性
经典示例:
- 配置复杂的GUI组件(窗口、对话框)
- 生成不同格式的文档(PDF、HTML、TXT)
- SQL查询语句的构建
- 消息或请求参数组装
4. C++代码示例
示例1:电脑组装(经典实现)
cpp
#include <iostream>
#include <string>
#include <vector>
// 产品:电脑
class Computer {
private:
std::string cpu_;
std::string gpu_;
int ram_;
int storage_;
std::vector<std::string> accessories_;
public:
void setCPU(const std::string& cpu) { cpu_ = cpu; }
void setGPU(const std::string& gpu) { gpu_ = gpu; }
void setRAM(int ram) { ram_ = ram; }
void setStorage(int storage) { storage_ = storage; }
void addAccessory(const std::string& accessory) {
accessories_.push_back(accessory);
}
void show() const {
std::cout << "电脑配置:\n"
<< " CPU: " << cpu_ << "\n"
<< " GPU: " << gpu_ << "\n"
<< " 内存: " << ram_ << "GB\n"
<< " 硬盘: " << storage_ << "GB\n"
<< " 配件: ";
for (const auto& acc : accessories_)
std::cout << acc << " ";
std::cout << std::endl;
}
};
// 抽象建造者
class ComputerBuilder {
public:
virtual ~ComputerBuilder() = default;
virtual void buildCPU() = 0;
virtual void buildGPU() = 0;
virtual void buildRAM() = 0;
virtual void buildStorage() = 0;
virtual void buildAccessories() = 0;
virtual Computer* getResult() = 0;
};
// 具体建造者:游戏电脑
class GamingComputerBuilder : public ComputerBuilder {
private:
Computer* computer_;
public:
GamingComputerBuilder() { computer_ = new Computer(); }
~GamingComputerBuilder() { delete computer_; }
void buildCPU() override { computer_->setCPU("Intel i9-13900K"); }
void buildGPU() override { computer_->setGPU("NVIDIA RTX 4090"); }
void buildRAM() override { computer_->setRAM(32); }
void buildStorage() override { computer_->setStorage(2000); }
void buildAccessories() override {
computer_->addAccessory("机械键盘");
computer_->addAccessory("电竞鼠标");
}
Computer* getResult() override { return computer_; }
};
// 具体建造者:办公电脑
class OfficeComputerBuilder : public ComputerBuilder {
private:
Computer* computer_;
public:
OfficeComputerBuilder() { computer_ = new Computer(); }
~OfficeComputerBuilder() { delete computer_; }
void buildCPU() override { computer_->setCPU("Intel i5-13400"); }
void buildGPU() override { computer_->setGPU("集成显卡"); }
void buildRAM() override { computer_->setRAM(16); }
void buildStorage() override { computer_->setStorage(512); }
void buildAccessories() override {
computer_->addAccessory("普通键盘");
computer_->addAccessory("办公鼠标");
}
Computer* getResult() override { return computer_; }
};
// 指挥者
class Director {
private:
ComputerBuilder* builder_;
public:
void setBuilder(ComputerBuilder* builder) { builder_ = builder; }
Computer* construct() {
builder_->buildCPU();
builder_->buildGPU();
builder_->buildRAM();
builder_->buildStorage();
builder_->buildAccessories();
return builder_->getResult();
}
};
// 使用示例
int main() {
Director director;
GamingComputerBuilder gamingBuilder;
director.setBuilder(&gamingBuilder);
Computer* gamingPC = director.construct();
gamingPC->show();
OfficeComputerBuilder officeBuilder;
director.setBuilder(&officeBuilder);
Computer* officePC = director.construct();
officePC->show();
delete gamingPC;
delete officePC;
return 0;
}
示例2:链式调用风格(现代C++)
cpp
#include <iostream>
#include <string>
class Pizza {
private:
std::string size_;
std::string crust_;
bool cheese_;
bool pepperoni_;
bool mushrooms_;
// 私有构造函数,只能通过Builder创建
Pizza() = default;
public:
class Builder {
private:
Pizza pizza_;
public:
Builder& setSize(const std::string& size) {
pizza_.size_ = size;
return *this;
}
Builder& setCrust(const std::string& crust) {
pizza_.crust_ = crust;
return *this;
}
Builder& addCheese() {
pizza_.cheese_ = true;
return *this;
}
Builder& addPepperoni() {
pizza_.pepperoni_ = true;
return *this;
}
Builder& addMushrooms() {
pizza_.mushrooms_ = true;
return *this;
}
Pizza build() {
// 可以添加验证逻辑
if (pizza_.size_.empty())
throw std::runtime_error("披萨尺寸不能为空");
return pizza_;
}
};
void show() const {
std::cout << "披萨: " << size_ << ", 饼底: " << crust_
<< ", 配料: ";
if (cheese_) std::cout << "芝士 ";
if (pepperoni_) std::cout << "意大利辣香肠 ";
if (mushrooms_) std::cout << "蘑菇 ";
std::cout << std::endl;
}
};
// 使用示例
int main() {
Pizza pizza = Pizza::Builder()
.setSize("大份")
.setCrust("薄脆")
.addCheese()
.addPepperoni()
.build();
pizza.show();
return 0;
}
5. 优缺点
优点:
- 分离构建和表示,封装性好
- 控制构建过程,易于扩展
- 可以逐步构建,延迟返回完整对象
- 参数可选,避免构造器重载爆炸
缺点:
- 需要额外创建Builder类,增加代码量
- 如果产品内部变化复杂,需要修改建造者
- 对简单对象可能过度设计
6. 与其他模式对比
| 模式 | 区别 |
|---|---|
| 工厂模式 | 一次性创建完整对象;建造者分步骤创建 |
| 抽象工厂 | 创建产品族;建造者创建复杂产品 |
| 原型模式 | 克隆对象;建造者新建对象 |
总结:当对象的构造过程复杂、需要多种表示、构造参数多且有可选参数时,优先考虑建造者模式。## 建造者模式详解
1. 概念
建造者模式是一种创建型设计模式 ,它将一个复杂对象的构建 与表示分离,使得同样的构建过程可以创建不同的表示。
2. 核心角色
- Product(产品):要构建的复杂对象
- Builder(抽象建造者):声明构建产品各部分的方法
- ConcreteBuilder(具体建造者):实现具体构建逻辑,并提供获取产品的方法
- Director(指挥者):定义构建顺序,负责使用Builder接口构建产品
3. 应用场景
适用情况:
- 构造参数多且部分可选(替代多参数构造函数)
- 对象包含多个相同类型的组件(如披萨配料)
- 需要生成不同表示形式的对象(不同配置的电脑)
- 需要控制建造顺序或校验有效性
经典示例:
- 配置复杂的GUI组件(窗口、对话框)
- 生成不同格式的文档(PDF、HTML、TXT)
- SQL查询语句的构建
- 消息或请求参数组装
4. C++代码示例
示例1:电脑组装(经典实现)
cpp
#include <iostream>
#include <string>
#include <vector>
// 产品:电脑
class Computer {
private:
std::string cpu_;
std::string gpu_;
int ram_;
int storage_;
std::vector<std::string> accessories_;
public:
void setCPU(const std::string& cpu) { cpu_ = cpu; }
void setGPU(const std::string& gpu) { gpu_ = gpu; }
void setRAM(int ram) { ram_ = ram; }
void setStorage(int storage) { storage_ = storage; }
void addAccessory(const std::string& accessory) {
accessories_.push_back(accessory);
}
void show() const {
std::cout << "电脑配置:\n"
<< " CPU: " << cpu_ << "\n"
<< " GPU: " << gpu_ << "\n"
<< " 内存: " << ram_ << "GB\n"
<< " 硬盘: " << storage_ << "GB\n"
<< " 配件: ";
for (const auto& acc : accessories_)
std::cout << acc << " ";
std::cout << std::endl;
}
};
// 抽象建造者
class ComputerBuilder {
public:
virtual ~ComputerBuilder() = default;
virtual void buildCPU() = 0;
virtual void buildGPU() = 0;
virtual void buildRAM() = 0;
virtual void buildStorage() = 0;
virtual void buildAccessories() = 0;
virtual Computer* getResult() = 0;
};
// 具体建造者:游戏电脑
class GamingComputerBuilder : public ComputerBuilder {
private:
Computer* computer_;
public:
GamingComputerBuilder() { computer_ = new Computer(); }
~GamingComputerBuilder() { delete computer_; }
void buildCPU() override { computer_->setCPU("Intel i9-13900K"); }
void buildGPU() override { computer_->setGPU("NVIDIA RTX 4090"); }
void buildRAM() override { computer_->setRAM(32); }
void buildStorage() override { computer_->setStorage(2000); }
void buildAccessories() override {
computer_->addAccessory("机械键盘");
computer_->addAccessory("电竞鼠标");
}
Computer* getResult() override { return computer_; }
};
// 具体建造者:办公电脑
class OfficeComputerBuilder : public ComputerBuilder {
private:
Computer* computer_;
public:
OfficeComputerBuilder() { computer_ = new Computer(); }
~OfficeComputerBuilder() { delete computer_; }
void buildCPU() override { computer_->setCPU("Intel i5-13400"); }
void buildGPU() override { computer_->setGPU("集成显卡"); }
void buildRAM() override { computer_->setRAM(16); }
void buildStorage() override { computer_->setStorage(512); }
void buildAccessories() override {
computer_->addAccessory("普通键盘");
computer_->addAccessory("办公鼠标");
}
Computer* getResult() override { return computer_; }
};
// 指挥者
class Director {
private:
ComputerBuilder* builder_;
public:
void setBuilder(ComputerBuilder* builder) { builder_ = builder; }
Computer* construct() {
builder_->buildCPU();
builder_->buildGPU();
builder_->buildRAM();
builder_->buildStorage();
builder_->buildAccessories();
return builder_->getResult();
}
};
// 使用示例
int main() {
Director director;
GamingComputerBuilder gamingBuilder;
director.setBuilder(&gamingBuilder);
Computer* gamingPC = director.construct();
gamingPC->show();
OfficeComputerBuilder officeBuilder;
director.setBuilder(&officeBuilder);
Computer* officePC = director.construct();
officePC->show();
delete gamingPC;
delete officePC;
return 0;
}
示例2:链式调用风格(现代C++)
cpp
#include <iostream>
#include <string>
class Pizza {
private:
std::string size_;
std::string crust_;
bool cheese_;
bool pepperoni_;
bool mushrooms_;
// 私有构造函数,只能通过Builder创建
Pizza() = default;
public:
class Builder {
private:
Pizza pizza_;
public:
Builder& setSize(const std::string& size) {
pizza_.size_ = size;
return *this;
}
Builder& setCrust(const std::string& crust) {
pizza_.crust_ = crust;
return *this;
}
Builder& addCheese() {
pizza_.cheese_ = true;
return *this;
}
Builder& addPepperoni() {
pizza_.pepperoni_ = true;
return *this;
}
Builder& addMushrooms() {
pizza_.mushrooms_ = true;
return *this;
}
Pizza build() {
// 可以添加验证逻辑
if (pizza_.size_.empty())
throw std::runtime_error("披萨尺寸不能为空");
return pizza_;
}
};
void show() const {
std::cout << "披萨: " << size_ << ", 饼底: " << crust_
<< ", 配料: ";
if (cheese_) std::cout << "芝士 ";
if (pepperoni_) std::cout << "意大利辣香肠 ";
if (mushrooms_) std::cout << "蘑菇 ";
std::cout << std::endl;
}
};
// 使用示例
int main() {
Pizza pizza = Pizza::Builder()
.setSize("大份")
.setCrust("薄脆")
.addCheese()
.addPepperoni()
.build();
pizza.show();
return 0;
}
5. 优缺点
优点:
- 分离构建和表示,封装性好
- 控制构建过程,易于扩展
- 可以逐步构建,延迟返回完整对象
- 参数可选,避免构造器重载爆炸
缺点:
- 需要额外创建Builder类,增加代码量
- 如果产品内部变化复杂,需要修改建造者
- 对简单对象可能过度设计
6. 与其他模式对比
| 模式 | 区别 |
|---|---|
| 工厂模式 | 一次性创建完整对象;建造者分步骤创建 |
| 抽象工厂 | 创建产品族;建造者创建复杂产品 |
| 原型模式 | 克隆对象;建造者新建对象 |
7.链式调用 vs 经典建造者模式
核心区别对比表
| 对比维度 | 经典模式 | 链式调用 |
|---|---|---|
| 角色完整性 | 完整:Director+Builder+Product | 简化:通常只有Builder+Product |
| 构建流程控制 | Director统一控制顺序 | 客户端直接控制顺序 |
| 代码复杂度 | 较高(4个类/接口) | 较低(2个类) |
| 扩展性 | 新增Builder类即可 | 修改Builder类内部 |
| 构建顺序复用 | Director可复用构建流程 | 需要客户端重新写调用链 |
| 参数校验时机 | Director调用后或Builder内 | Builder的build()方法内 |
7.1 角色职责差异
经典模式:
cpp
// Director封装了构建顺序
class Director {
Computer* construct() {
builder->buildCPU(); // 固定顺序
builder->buildGPU(); // 不可变
builder->buildRAM();
return builder->getResult();
}
};
链式调用:
cpp
// 客户端控制顺序,顺序灵活但易出错
Pizza pizza = Pizza::Builder()
.addCheese() // 客户端随意排列
.setSize("大")
.setCrust("薄脆") // 顺序完全由调用者决定
.build();
7.2 复杂度权衡
| 场景 | 推荐模式 | 原因 |
|---|---|---|
| 构建步骤3-5个且固定 | 链式 | 简洁直观 |
| 构建步骤>5个且流程多变 | 经典 | Director可管理复杂流程 |
| 需要多种构建算法 | 经典 | 不同Director实现 |
| 参数多但有默认值 | 链式 | 可选参数友好 |
| 产品内部结构复杂 | 经典 | 更好的封装 |
7.3 实际代码对比示例
cpp
// ========== 场景:构建SQL查询 ==========
// 经典模式:适合复杂查询
class SQLQuery { /* ... */ };
class SQLBuilder {
public:
virtual void buildSelect() = 0;
virtual void buildFrom() = 0;
virtual void buildWhere() = 0;
virtual void buildOrderBy() = 0;
virtual SQLQuery* getResult() = 0;
};
class MySQLBuilder : public SQLBuilder { /* 实现 */ };
class PostgresBuilder : public SQLBuilder { /* 实现 */ };
class QueryDirector {
SQLQuery* buildComplexReport() { // 复用固定流程
builder->buildSelect();
builder->buildFrom();
builder->buildWhere();
builder->buildOrderBy();
return builder->getResult();
}
};
// 链式模式:适合简单查询
class SimpleQuery {
public:
class Builder {
SimpleQuery query;
public:
Builder& select(std::string cols) { /* ... */ return *this; }
Builder& from(std::string table) { /* ... */ return *this; }
Builder& where(std::string cond) { /* ... */ return *this; }
SimpleQuery build() { return query; }
};
};
// 客户端使用
SimpleQuery q = SimpleQuery::Builder()
.select("*")
.from("users")
.where("age > 18")
.build();
选择建议
使用经典模式当:
- ✅ 构建算法需要在多处复用
- ✅ 有多种不同的构建算法变体
- ✅ 构建步骤有严格的顺序依赖
- ✅ 产品对象非常复杂(20+属性)
- ✅ 需要支持多种产品变体(不同Builder)
使用链式调用当:
- ✅ 参数多但有合理默认值(如网络请求配置)
- ✅ 构建步骤简单且每个对象独立
- ✅ 客户端需要灵活控制构建过程
- ✅ 不需要多种构建算法变体
- ✅ 希望API具有流畅的编程体验
混合用法(最佳实践)
cpp
// 保留复杂产品的链式API + Director支持
class ComplexProduct {
public:
class Builder {
// 链式API
};
};
class Director {
public:
ComplexProduct buildStandard() {
return ComplexProduct::Builder()
.step1()
.step2()
.step3()
.build();
}
ComplexProduct buildAdvanced() {
return ComplexProduct::Builder()
.step3() // 不同顺序
.step1()
.step2()
.build();
}
};
总结 :经典模式重流程复用 ,链式调用重使用便利性。根据团队习惯和复杂度选择,必要时可混合使用。