02.C++设计模式—建造者模式详解

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();
    }
};

总结 :经典模式重流程复用 ,链式调用重使用便利性。根据团队习惯和复杂度选择,必要时可混合使用。

相关推荐
诙_2 小时前
深入理解C++设计模式
c++·设计模式
昵称小白2 小时前
C++ 刷题语法速查
c++·算法
Qt程序员2 小时前
【无标题】
linux·c++·消息队列·共享内存·c/c++·管道·信号量
十五年专注C++开发3 小时前
Qt程序设计涉及到的开发软件
开发语言·c++·qt
邪修king4 小时前
C++ typename & auto 彻底讲透:核心作用、推导规则、避坑指南
开发语言·c++
姆路4 小时前
Qt尺寸策略
c++·qt
khalil10205 小时前
代码随想录算法训练营Day-41动态规划08 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III
数据结构·c++·算法·leetcode·动态规划
Vect__5 小时前
C++无痛转go第一天,从hello world到切片
开发语言·c++·golang
无限进步_5 小时前
【C++】AVL树完全解析:从平衡因子到四种旋转
c语言·开发语言·数据结构·c++·后端·算法·github