c++注意点(12)----设计模式(生成器)
创建型模式
生成器模式(Builder Pattern)是一种创建型设计模式,它专注于将复杂对象的构建过程与表示分离,使得同样的构建过程可以创建不同的表示。
就像是做饭,你可以自己慢慢做,各个步骤自己选择。而使用生成器就像是预制菜,所有的最后菜的样子,已经规划好了。你只能从中选择一个。
为什么需要生成器模式?
当我们需要创建具有复杂内部结构的对象(比如包含多个部件、构建步骤繁琐或有多种配置方式的对象)时,直接在构造函数中处理会导致:
- 构造函数参数过多,难以维护(比如创建一个 \"电脑\" 对象,需要指定 CPU、内存、硬盘、显卡等十几种参数);
- 不同配置的对象需要不同的构建逻辑,导致代码臃肿;
- 构建过程与对象表示耦合,无法灵活切换不同的构建方式
举个生活中的例子
想象你去电脑店组装一台电脑,整个过程其实很复杂:
- 需要选很多零件(CPU、内存、硬盘、显卡等);
- 零件之间有搭配要求(比如主板要兼容 CPU);
- 组装有固定步骤(先装主板,再插 CPU,最后装机箱);
- 不同需求选的零件不同(办公用不需要好显卡,游戏用需要大内存)。
如果没有生成器模式,就像你自己去买零件、自己组装:
- 要记住所有零件型号和搭配规则,很容易出错;
- 每次换配置(比如从办公电脑换成游戏电脑),都要重新学一遍选零件和组装的流程;
- 步骤错了(比如先装显卡再装主板),可能装不上。
生成器模式就像请了一个专业装机师傅(生成器)和一个客户经理(指挥者):
- 你只需要告诉客户经理 “我要一台办公电脑”,不用管具体零件和步骤;
- 装机师傅知道所有零件搭配规则和组装顺序,会按步骤一步步装好;
- 想换游戏电脑?换一个擅长装游戏电脑的师傅(另一个生成器)就行,你不用学新东西。
示例
#include #include // 最终产品:电脑class Computer {private: std::string cpu_; // 处理器 std::string memory_; // 内存 std::string hardDisk_; // 硬盘 std::string graphics_; // 显卡 std::string power_; // 电源public: // 设置各部件(让生成器可以修改内部属性) void setCPU(const std::string& cpu) { cpu_ = cpu; } void setMemory(const std::string& memory) { memory_ = memory; } void setHardDisk(const std::string& hardDisk) { hardDisk_ = hardDisk; } void setGraphics(const std::string& graphics) { graphics_ = graphics; } void setPower(const std::string& power) { power_ = power; } // 获取各部件信息 std::string getCPU() const { return cpu_; } std::string getMemory() const { return memory_; } std::string getHardDisk() const { return hardDisk_; } std::string getGraphics() const { return graphics_; } std::string getPower() const { return power_; } // 显示电脑配置 void showConfig() const { std::cout << \"电脑配置:\\n\"; std::cout << \"CPU:\" << cpu_ << \"\\n\"; std::cout << \"内存:\" << memory_ << \"\\n\"; std::cout << \"硬盘:\" << hardDisk_ << \"\\n\"; std::cout << \"显卡:\" << graphics_ << \"\\n\"; std::cout << \"电源:\" << power_ << \"\\n\\n\"; }};// 生成器接口(抽象类):定义组装步骤class Builder {protected: Computer computer_; // 正在组装的电脑public: // 纯虚函数:组装各部件的步骤 virtual void buildCPU() = 0; virtual void buildMemory() = 0; virtual void buildHardDisk() = 0; virtual void buildGraphics() = 0; virtual void buildPower() = 0; // 返回组装好的电脑 virtual Computer getComputer() { return computer_; } // 虚析构函数 virtual ~Builder() = default;};// 具体生成器1:办公电脑生成器class OfficeBuilder : public Builder {public: void buildCPU() override { computer_.setCPU(\"英特尔 i5(入门级)\"); std::cout << \"安装办公电脑CPU:\" << computer_.getCPU() << \"\\n\"; } void buildMemory() override { computer_.setMemory(\"8G DDR4\"); std::cout << \"安装办公电脑内存:\" << computer_.getMemory() << \"\\n\"; } void buildHardDisk() override { computer_.setHardDisk(\"512G 固态硬盘\"); std::cout << \"安装办公电脑硬盘:\" << computer_.getHardDisk() << \"\\n\"; } void buildGraphics() override { computer_.setGraphics(\"集成显卡\"); std::cout << \"安装办公电脑显卡:\" << computer_.getGraphics() << \"\\n\"; } void buildPower() override { computer_.setPower(\"300W 电源\"); std::cout << \"安装办公电脑电源:\" << computer_.getPower() << \"\\n\"; }};// 具体生成器2:游戏电脑生成器class GameBuilder : public Builder {public: void buildCPU() override { computer_.setCPU(\"英特尔 i7(高性能)\"); std::cout << \"安装游戏电脑CPU:\" << computer_.getCPU() << \"\\n\"; } void buildMemory() override { computer_.setMemory(\"16G DDR5\"); std::cout << \"安装游戏电脑内存:\" << computer_.getMemory() << \"\\n\"; } void buildHardDisk() override { computer_.setHardDisk(\"1T 固态硬盘\"); std::cout << \"安装游戏电脑硬盘:\" << computer_.getHardDisk() << \"\\n\"; } void buildGraphics() override { computer_.setGraphics(\"RTX 4060 独立显卡\"); std::cout << \"安装游戏电脑显卡:\" << computer_.getGraphics() << \"\\n\"; } void buildPower() override { computer_.setPower(\"500W 电源\"); std::cout << \"安装游戏电脑电源:\" << computer_.getPower() << \"\\n\"; }};// 指挥者:负责控制组装流程class Director {private: Builder* builder_; // 指向当前使用的生成器public: // 构造函数:传入生成器 Director(Builder* builder) : builder_(builder) {} // 指挥组装电脑(固定步骤) Computer construct() { std::cout <buildCPU(); builder_->buildMemory(); builder_->buildHardDisk(); builder_->buildGraphics(); builder_->buildPower(); std::cout <getComputer(); }};// 客户端:用户购买电脑int main() { // 1. 准备生成器(装机师傅) OfficeBuilder officeBuilder; // 办公电脑装机师傅 GameBuilder gameBuilder; // 游戏电脑装机师傅 // 2. 准备指挥者(客户经理) Director director(nullptr); // 3. 组装办公电脑 std::cout << \"=== 组装办公电脑 ===\\n\"; director = Director(&officeBuilder); // 安排办公装机师傅 Computer officeComputer = director.construct(); // 开始组装 officeComputer.showConfig(); // 查看配置 // 4. 组装游戏电脑 std::cout << \"=== 组装游戏电脑 ===\\n\"; director = Director(&gameBuilder); // 换游戏装机师傅 Computer gameComputer = director.construct(); // 开始组装 gameComputer.showConfig(); // 查看配置 return 0;}
当然。有些参数是不一定使用的,可以选择使用哪些。那么这里给出第二个示例,用于参考,额外的参数配置部分。
#include #include #include // 电脑产品(支持可选配件)class Computer {private: std::string cpu_; // 必选:CPU std::string memory_; // 必选:内存 std::string hardDisk_; // 必选:硬盘 std::string graphics_; // 可选:显卡(核显/独显) std::string power_; // 必选:电源 std::vector extras_; // 可选:额外配件(如散热器、蓝牙模块)public: // 设置必选部件 void setCPU(const std::string& cpu) { cpu_ = cpu; } void setMemory(const std::string& memory) { memory_ = memory; } void setHardDisk(const std::string& hardDisk) { hardDisk_ = hardDisk; } void setPower(const std::string& power) { power_ = power; } // 设置可选部件 void setGraphics(const std::string& graphics) { graphics_ = graphics; } void addExtra(const std::string& extra) { extras_.push_back(extra); } // 获取部件信息(用于生成器输出) std::string getCPU() const { return cpu_; } std::string getMemory() const { return memory_; } std::string getHardDisk() const { return hardDisk_; } std::string getGraphics() const { return graphics_; } std::string getPower() const { return power_; } // 显示配置(区分必选和可选) void showConfig() const { std::cout << \"===== 电脑配置 =====\" << \"\\n\"; std::cout << \"【必选部件】\\n\"; std::cout << \"CPU:\" << cpu_ << \"\\n\"; std::cout << \"内存:\" << memory_ << \"\\n\"; std::cout << \"硬盘:\" << hardDisk_ << \"\\n\"; std::cout << \"电源:\" << power_ << \"\\n\"; std::cout << \"\\n【可选部件】\\n\"; std::cout << \"显卡:\" << (graphics_.empty() ? \"无(使用核显)\" : graphics_) << \"\\n\"; std::cout << \"额外配件:\"; if (extras_.empty()) { std::cout << \"无\"; } else { for (const auto& extra : extras_) { std::cout << extra << \"、\"; } } std::cout << \"\\n====================\\n\\n\"; }};// 生成器接口(支持可选步骤)class Builder {protected: Computer computer_;public: // 必选步骤(纯虚函数,必须实现) virtual void buildCPU() = 0; virtual void buildMemory() = 0; virtual void buildHardDisk() = 0; virtual void buildPower() = 0; // 可选步骤(虚函数,默认空实现,可选择性重写) virtual void buildGraphics() {} // 可选:装独立显卡 virtual void addExtra(const std::string& extra) { // 可选:加配件 computer_.addExtra(extra); } virtual Computer getComputer() { return computer_; } virtual ~Builder() = default;};// 具体生成器1:极简办公电脑(不选独显,不加额外配件)class MinimalOfficeBuilder : public Builder {public: void buildCPU() override { computer_.setCPU(\"英特尔 i3(低功耗)\"); std::cout << \"安装CPU:\" << computer_.getCPU() << \"\\n\"; } void buildMemory() override { computer_.setMemory(\"4G DDR4\"); std::cout << \"安装内存:\" << computer_.getMemory() << \"\\n\"; } void buildHardDisk() override { computer_.setHardDisk(\"256G 固态硬盘\"); std::cout << \"安装硬盘:\" << computer_.getHardDisk() << \"\\n\"; } void buildPower() override { computer_.setPower(\"200W 电源\"); std::cout << \"安装电源:\" << computer_.getPower() << \"\\n\"; } // 不重写buildGraphics(),使用默认空实现(不装独显) // 不调用addExtra(),所以无额外配件};// 具体生成器2:高端游戏电脑(选独显,加多个配件)class HighEndGameBuilder : public Builder {public: void buildCPU() override { computer_.setCPU(\"AMD Ryzen 9(旗舰级)\"); std::cout << \"安装CPU:\" << computer_.getCPU() << \"\\n\"; } void buildMemory() override { computer_.setMemory(\"32G DDR5\"); std::cout << \"安装内存:\" << computer_.getMemory() << \"\\n\"; } void buildHardDisk() override { computer_.setHardDisk(\"2T 固态硬盘\"); std::cout << \"安装硬盘:\" << computer_.getHardDisk() << \"\\n\"; } void buildPower() override { computer_.setPower(\"800W 金牌电源\"); std::cout << \"安装电源:\" << computer_.getPower() << \"\\n\"; } // 重写可选步骤:安装独显 void buildGraphics() override { computer_.setGraphics(\"RTX 4090 独显\"); std::cout << \"安装显卡:\" << computer_.getGraphics() << \"\\n\"; }};// 指挥者(支持灵活调整步骤)class Director {private: Builder* builder_;public: Director(Builder* builder) : builder_(builder) {} // 基础组装(只包含必选步骤) Computer buildBasic() { std::cout <buildCPU(); builder_->buildMemory(); builder_->buildHardDisk(); builder_->buildPower(); std::cout <getComputer(); } // 完整组装(必选+可选步骤) Computer buildComplete() { std::cout <buildGraphics(); // 可选:装显卡 builder_->addExtra(\"水冷散热器\"); // 可选:加配件 builder_->addExtra(\"蓝牙模块\"); // 可选:加配件 std::cout <getComputer(); }};// 客户端:灵活定制不同配置int main() { // 1. 组装极简办公电脑(只装必选部件) MinimalOfficeBuilder officeBuilder; Director officeDirector(&officeBuilder); Computer officePC = officeDirector.buildBasic(); // 只调用必选步骤 officePC.showConfig(); // 2. 组装高端游戏电脑(必选+可选部件) HighEndGameBuilder gameBuilder; Director gameDirector(&gameBuilder); Computer gamePC = gameDirector.buildComplete(); // 调用必选+可选步骤 gamePC.showConfig(); // 3. 临时加配件(生成器模式支持中途调整) std::cout << \"给办公电脑临时加一个配件:\\n\"; officeBuilder.addExtra(\"无线网卡\"); officePC = officeBuilder.getComputer(); officePC.showConfig(); return 0;}
优势
1.使用生成器模式可避免 “重叠构造函数 (telescoping constructor)” 的出现。
假设你的构造函数中有十个可选参数, 那么调用该函数会非常不方便; 因此, 你需要重载这个构造函数, 新建几个只有较少参数的简化版。 但这些构造函数仍需调用主构造函数, 传递一些默认数值来替代省略掉的参数。
class Pizza { Pizza(int size) { …… } Pizza(int size, boolean cheese) { …… } Pizza(int size, boolean cheese, boolean pepperoni) { …… }//............
生成器模式让你可以分步骤生成对象, 而且允许你仅使用必须的步骤。 应用该模式后, 你再也不需要将几十个参数塞进构造函数里了。