在C++的面向对象开发中,建造者模式是处理复杂对象创建场景的常用设计模式,流式接口则能让方法调用形成连贯的链式结构。将两者结合可以让复杂对象的创建过程更清晰、代码可读性更高,下面详细介绍具体的实现方式和优势。

核心概念说明
建造者模式
建造者模式将复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。它通常包含产品类、抽象建造者、具体建造者和指挥者四个角色,适合创建包含多个可选配置项的对象。
流式接口
流式接口是指方法的返回值是对象自身的引用,这样可以在同一个对象上连续调用多个方法,形成类似流式的调用效果,减少临时变量的定义,让代码更简洁。
结合实现示例
假设我们需要创建一个电脑对象,电脑包含CPU、内存、硬盘、显卡等配置,其中CPU和内存是必选配置,硬盘和显卡是可选配置,适合用建造者模式结合流式接口实现。
产品类定义
首先定义电脑产品类,成员变量设置为私有,只通过建造者类进行修改:
#include <string>
#include <iostream>
// 电脑产品类
class Computer {
private:
std::string cpu; // 必选:CPU
std::string memory; // 必选:内存
std::string disk; // 可选:硬盘
std::string gpu; // 可选:显卡
// 构造函数私有化,只能通过建造者创建
Computer() = default;
public:
// 获取配置信息的方法
void showConfig() const {
std::cout << "电脑配置:" << std::endl;
std::cout << "CPU: " << cpu << std::endl;
std::cout << "内存: " << memory << std::endl;
if (!disk.empty()) {
std::cout << "硬盘: " << disk << std::endl;
}
if (!gpu.empty()) {
std::cout << "显卡: " << gpu << std::endl;
}
}
// 建造者类作为内部类
class Builder {
private:
Computer computer;
public:
// 设置必选CPU,返回自身引用实现流式调用
Builder& setCpu(const std::string& cpu) {
computer.cpu = cpu;
return *this;
}
// 设置必选内存,返回自身引用实现流式调用
Builder& setMemory(const std::string& memory) {
computer.memory = memory;
return *this;
}
// 设置可选硬盘,返回自身引用实现流式调用
Builder& setDisk(const std::string& disk) {
computer.disk = disk;
return *this;
}
// 设置可选显卡,返回自身引用实现流式调用
Builder& setGpu(const std::string& gpu) {
computer.gpu = gpu;
return *this;
}
// 构建最终产品,返回电脑对象
Computer build() {
// 校验必选参数
if (computer.cpu.empty() || computer.memory.empty()) {
throw std::invalid_argument("CPU和内存为必选配置");
}
return computer;
}
};
};
使用示例
通过流式接口调用建造者的方法,创建不同配置的电脑对象:
int main() {
try {
// 创建高配电脑,链式调用设置所有配置
Computer highConfigComputer = Computer::Builder()
.setCpu("i9-13900K")
.setMemory("32GB DDR5")
.setDisk("2TB NVMe SSD")
.setGpu("RTX 4090")
.build();
std::cout << "高配电脑信息:" << std::endl;
highConfigComputer.showConfig();
std::cout << std::endl;
// 创建基础办公电脑,只设置必选配置
Computer officeComputer = Computer::Builder()
.setCpu("i5-12400")
.setMemory("16GB DDR4")
.build();
std::cout << "办公电脑信息:" << std::endl;
officeComputer.showConfig();
} catch (const std::exception& e) {
std::cout << "创建失败:" << e.what() << std::endl;
}
return 0;
}
结合的优势
- 代码可读性更高:链式调用让配置过程一目了然,不需要定义多个临时变量,也能清晰看到每个配置项的设置顺序。
- 参数校验更集中:所有参数的校验逻辑都放在
build()方法中,避免创建出不完整的对象。 - 扩展更方便:如果需要新增配置项,只需要在建造者类中添加新的设置方法,返回自身引用即可,不需要修改产品类的构造逻辑。
- 必选可选配置区分明确:通过建造者的方法调用可以直观区分哪些是必选配置,哪些是可选配置,减少参数传递的错误。
注意事项
实现时需要注意产品类的构造函数要私有化,避免外部直接创建对象,确保所有对象都通过建造者创建。同时流式接口的方法返回值必须是对象自身的引用,否则无法形成链式调用。如果配置项较多,还可以在建造者类中添加重置方法,方便复用建造者对象创建多个相似配置的产品。