设计模式:建造者模式
文章目录
- 一、建造者模式的基本概念
- 二、建造者模式结构
- 三、示例代码
一、建造者模式的基本概念
建造者模式(亦称:生成器模式)是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 将一个复杂对象的构建过程与它的表示 分离,使得同样的构建过程可以创建不同的表示。
- 意图:处理复杂对象的创建问题,尤其是需要分步骤组装的对象。
- 核心思想:把复杂对象的创建过程抽象出来,使用不同的“建造者”来构造不同的表示。
使用场景:
- 对象构建复杂:对象有很多组成部分,且构建步骤固定,但具体实现不同。
- 同样的构建过程,不同的表示:比如:
- 游戏中创建不同风格的角色(武士、法师)。
- 生成不同格式的报表(PDF、HTML、Excel)。
- 组装汽车(跑车、越野车)。
总结:
- 建造者模式更适合“复杂对象的分步骤组装”。
- 相比工厂模式,建造者模式更关注“组装过程”。
二、建造者模式结构
角色组成:
- Product(产品类):最终要创建的复杂对象;由多个部件组成。
- Builder(抽象建造者):规定创建产品的抽象步骤(通常有 buildPartA()、buildPartB() 等)。不涉及具体部件的实现。
- ConcreteBuilder(具体建造者):实现 Builder 的接口,具体完成产品部件的创建。最终返回一个完整的 Product。
- Director(指挥者):调用建造者的步骤方法,控制构建过程。不关心具体的产品细节,只负责组装。
UML类图:
说明:
- Product(抽象产品):定义了产品的公共接口。
- ConcreteProductA / ConcreteProductB(具体产品):实现 Product 接口,不同的产品有不同的行为。
- Factory(工厂类):提供一个静态方法 createProduct(type),根据参数决定创建哪一种 Product 实例。
三、示例代码
3.1基本示例
#include <iostream>
#include <string>
using namespace std;// 产品类
class Product {
public:void setPartA(const string& part) { partA = part; }void setPartB(const string& part) { partB = part; }void show() {cout << "Product parts: " << partA << ", " << partB << endl;}
private:string partA;string partB;
};// 抽象建造者
class Builder {
public:virtual ~Builder() {}virtual void buildPartA() = 0;virtual void buildPartB() = 0;virtual Product* getResult() = 0;
};// 具体建造者
class ConcreteBuilder : public Builder {
public:ConcreteBuilder() { product = new Product(); }void buildPartA() override { product->setPartA("Part A"); }void buildPartB() override { product->setPartB("Part B"); }Product* getResult() override { return product; }
private:Product* product;
};// 指挥者
class Director {
public:Director(Builder* b) : builder(b) {}Product* construct() {builder->buildPartA();builder->buildPartB();return builder->getResult();}
private:Builder* builder;
};// 使用示例
int main() {Builder* builder = new ConcreteBuilder();Director director(builder);Product* product = director.construct();product->show();delete product;delete builder;return 0;
}
3.2 构建一个复杂的 QWidget 界面(包含标题、按钮、输入框等)
需求场景:
- 我们要创建一个 不同风格的界面(比如 登录界面、注册界面)。
- 构建过程是固定的:添加标题 → 添加输入框 → 添加按钮。
- 使用建造者模式来灵活组装。
示例代码:
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>// ================= Product =================
class ComplexWidget : public QWidget {
public:ComplexWidget(QWidget *parent = nullptr) : QWidget(parent) {layout = new QVBoxLayout(this);setLayout(layout);}void addTitle(const QString &text) {QLabel *label = new QLabel(text, this);label->setAlignment(Qt::AlignCenter);layout->addWidget(label);}void addInput(const QString &placeholder) {QLineEdit *edit = new QLineEdit(this);edit->setPlaceholderText(placeholder);layout->addWidget(edit);}void addButton(const QString &text) {QPushButton *btn = new QPushButton(text, this);layout->addWidget(btn);}private:QVBoxLayout *layout;
};// ================= Builder =================
class Builder {
public:virtual ~Builder() {}virtual void buildTitle() = 0;virtual void buildInputs() = 0;virtual void buildButtons() = 0;virtual ComplexWidget* getResult() = 0;
};// ================= ConcreteBuilder: 登录界面 =================
class LoginBuilder : public Builder {
public:LoginBuilder() { widget = new ComplexWidget(); }void buildTitle() override {widget->addTitle("用户登录");}void buildInputs() override {widget->addInput("用户名");widget->addInput("密码");}void buildButtons() override {widget->addButton("登录");widget->addButton("取消");}ComplexWidget* getResult() override { return widget; }
private:ComplexWidget *widget;
};// ================= ConcreteBuilder: 注册界面 =================
class RegisterBuilder : public Builder {
public:RegisterBuilder() { widget = new ComplexWidget(); }void buildTitle() override {widget->addTitle("用户注册");}void buildInputs() override {widget->addInput("用户名");widget->addInput("邮箱");widget->addInput("密码");widget->addInput("确认密码");}void buildButtons() override {widget->addButton("注册");widget->addButton("返回");}ComplexWidget* getResult() override { return widget; }
private:ComplexWidget *widget;
};// ================= Director =================
class Director {
public:Director(Builder *b) : builder(b) {}ComplexWidget* construct() {builder->buildTitle();builder->buildInputs();builder->buildButtons();return builder->getResult();}
private:Builder *builder;
};// ================= main =================
int main(int argc, char *argv[]) {QApplication app(argc, argv);// 选择不同的 BuilderBuilder *builder = nullptr;// 登录界面builder = new LoginBuilder();Director directorLogin(builder);ComplexWidget *loginWidget = directorLogin.construct();loginWidget->setWindowTitle("建造者模式 - 登录界面");loginWidget->show();delete builder;// 注册界面builder = new RegisterBuilder();Director directorRegister(builder);ComplexWidget *registerWidget = directorRegister.construct();registerWidget->setWindowTitle("建造者模式 - 注册界面");registerWidget->move(400, 100);registerWidget->show();delete builder;return app.exec();
}
3.2.日常类比示例
示例场景:
- 一辆汽车由发动机、车轮、车身 三部分组成。
- 我们可以用同样的构建步骤,来造不同类型的车(比如跑车、SUV)。
- 使用 建造者模式 来封装“组装过程”。
#include <iostream>
#include <string>
using namespace std;// ================= Product: 汽车 =================
class Car {
public:void setEngine(const string &e) { engine = e; }void setWheels(const string &w) { wheels = w; }void setBody(const string &b) { body = b; }void show() {cout << "这是一辆车: "<< body << ", " << engine << ", " << wheels << endl;}
private:string engine;string wheels;string body;
};// ================= Builder 抽象建造者 =================
class Builder {
public:virtual ~Builder() {}virtual void buildEngine() = 0;virtual void buildWheels() = 0;virtual void buildBody() = 0;virtual Car* getResult() = 0;
};// ================= 具体建造者: 跑车 =================
class SportsCarBuilder : public Builder {
public:SportsCarBuilder() { car = new Car(); }void buildEngine() override { car->setEngine("V8 发动机"); }void buildWheels() override { car->setWheels("18寸跑车轮胎"); }void buildBody() override { car->setBody("流线型跑车车身"); }Car* getResult() override { return car; }
private:Car *car;
};// ================= 具体建造者: SUV =================
class SUVBuilder : public Builder {
public:SUVBuilder() { car = new Car(); }void buildEngine() override { car->setEngine("V6 涡轮发动机"); }void buildWheels() override { car->setWheels("20寸越野轮胎"); }void buildBody() override { car->setBody("高底盘SUV车身"); }Car* getResult() override { return car; }
private:Car *car;
};// ================= Director 指挥者 =================
class Director {
public:Director(Builder *b) : builder(b) {}Car* construct() {builder->buildEngine();builder->buildWheels();builder->buildBody();return builder->getResult();}
private:Builder *builder;
};// ================= 使用示例 =================
int main() {// 生产跑车Builder *sportsBuilder = new SportsCarBuilder();Director director1(sportsBuilder);Car *sportsCar = director1.construct();sportsCar->show();// 生产SUVBuilder *suvBuilder = new SUVBuilder();Director director2(suvBuilder);Car *suvCar = director2.construct();suvCar->show();delete sportsCar;delete sportsBuilder;delete suvCar;delete suvBuilder;return 0;
}