设计模式:建造者模式

文章目录

一、建造者模式的基本概念

建造者模式(亦称:生成器模式)是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 将一个复杂对象的构建过程与它的表示 分离,使得同样的构建过程可以创建不同的表示。

  • 意图:处理复杂对象的创建问题,尤其是需要分步骤组装的对象。
  • 核心思想:把复杂对象的创建过程抽象出来,使用不同的"建造者"来构造不同的表示。


使用场景:

  • 对象构建复杂:对象有很多组成部分,且构建步骤固定,但具体实现不同。
  • 同样的构建过程,不同的表示:比如:
    • 游戏中创建不同风格的角色(武士、法师)。
    • 生成不同格式的报表(PDF、HTML、Excel)。
    • 组装汽车(跑车、越野车)。

总结:

  • 建造者模式更适合"复杂对象的分步骤组装"。
  • 相比工厂模式,建造者模式更关注"组装过程"。

二、建造者模式结构

角色组成:

  • Product(产品类):最终要创建的复杂对象;由多个部件组成。
  • Builder(抽象建造者):规定创建产品的抽象步骤(通常有 buildPartA()、buildPartB() 等)。不涉及具体部件的实现。
  • ConcreteBuilder(具体建造者):实现 Builder 的接口,具体完成产品部件的创建。最终返回一个完整的 Product。
  • Director(指挥者):调用建造者的步骤方法,控制构建过程。不关心具体的产品细节,只负责组装。

UML类图:

说明:

  • Product(抽象产品):定义了产品的公共接口。
  • ConcreteProductA / ConcreteProductB(具体产品):实现 Product 接口,不同的产品有不同的行为。
  • Factory(工厂类):提供一个静态方法 createProduct(type),根据参数决定创建哪一种 Product 实例。

三、示例代码

3.1基本示例

cpp 复制代码
#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 界面(包含标题、按钮、输入框等)

需求场景:

  • 我们要创建一个 不同风格的界面(比如 登录界面、注册界面)。
  • 构建过程是固定的:添加标题 → 添加输入框 → 添加按钮。
  • 使用建造者模式来灵活组装。

示例代码:

cpp 复制代码
#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);

    // 选择不同的 Builder
    Builder *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)。
  • 使用 建造者模式 来封装"组装过程"。
cpp 复制代码
#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();

    // 生产SUV
    Builder *suvBuilder = new SUVBuilder();
    Director director2(suvBuilder);
    Car *suvCar = director2.construct();
    suvCar->show();

    delete sportsCar;
    delete sportsBuilder;
    delete suvCar;
    delete suvBuilder;
    return 0;
}