04创建型设计模式——建造者模式

一、建造者模式简介

建造者模式(Builder Pattern)又被称为生成器模式。它旨在构建一个复杂对象的各个部分,而不需要指定该对象的具体类。该模式特别适用于对象的构建过程复杂且需要多个步骤的情况。建造者模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象。

建造者模式适用于:当一个对象的构建比较复杂,将一个对象的构建(?)和对象的表示(?)进行分离的情况

  1. 分离构建和表示

    建造者模式通过将复杂对象的构建过程与其表示分离开来,允许构建过程的变化不会影响到最终对象的表示。也就是说,构建者模式关注的是如何一步一步地构建一个对象,而不是最终对象是什么样的。

  2. 逐步构建

    该模式允许通过多个步骤(方法)来逐步构建对象,这些步骤可以是可选的或者是必需的。构建的顺序和内容可以被灵活控制。

GoF一书中对建造者模式的介绍

二、建造者模式的用处

1. 复杂对象的构建

当一个对象的构建过程包含多个步骤或组件时,建造者模式可以帮助将这些步骤分开,从而使构建过程更加清晰和易于管理。例如,构建一个具有多种配置选项的复杂数据结构或图形用户界面(GUI)组件。

2. 构建过程的灵活性

建造者模式允许灵活地定制对象的创建过程,而无需修改对象的具体实现。例如,不同的建造者可以用于创建具有不同配置或特性的对象,而指挥者(Director)负责控制构建的步骤和顺序。

3. 解耦构建和表示

将对象的构建过程与表示分离,使得构建的过程和最终的对象类型可以独立变化。这种解耦使得系统更加灵活,易于扩展和维护。例如,你可以在不修改对象创建逻辑的情况下添加新的产品类型或更改产品的外观。

4. 支持逐步构建

对于需要逐步构建的对象,建造者模式可以逐步执行构建步骤。这样可以在构建过程中控制每个步骤的执行,并允许有选择地构建对象。例如,在构建复杂的报告或文档时,你可以按章节、段落等逐步添加内容。

5. 提高代码可读性和可维护性

通过将构建过程分解成多个清晰的步骤,建造者模式使得代码更加易读和易于维护。每个建造者只负责对象的一个方面的构建,使得构建过程更加模块化。

6. 支持复杂的构建逻辑

当对象的构建逻辑非常复杂,需要处理多种条件或选项时,建造者模式可以封装这些复杂的逻辑。这样,可以将构建逻辑集中在建造者类中,而客户端代码只需知道如何使用指挥者来创建对象

三、建造者模式的设计方法

builder.cpp

cpp 复制代码
#include <iostream>
#include <string>
#include <memory>

// 产品
class House {
public:
    void setDoor(const std::string& door) {
        this->door = door;
    }

    void setWall(const std::string& wall) {
        this->wall = wall;
    }

    void setWindow(const std::string& window) {
        this->window = window;
    }

    void setFloor(const std::string& floor) {
        this->floor = floor;
    }

    const std::string& getDoor() const {
        return this->door;
    }

    const std::string& getWall() const {
        return this->wall;
    }

    const std::string& getWindow() const {
        return this->window;
    }

    const std::string& getFloor() const {
        return this->floor;
    }

protected:
    std::string door;
    std::string wall;
    std::string window;
    std::string floor;
};

// 工程队
class Builder {
public:
    virtual ~Builder() {}

    virtual void buildWall() = 0;
    virtual void buildDoor() = 0;
    virtual void buildWindow() = 0;
    virtual void buildFloor() = 0;
    virtual std::shared_ptr<House> getHouse() = 0;
    virtual void viewHouse() const = 0; // 标记为 const
};

class VillaBuilder : public Builder {
public:
    VillaBuilder() : house(std::make_shared<House>()) {}

    void buildWall() override {
        house->setWall("别墅墙");
    }

    void buildDoor() override {
        house->setDoor("别墅门");
    }

    void buildWindow() override {
        house->setWindow("别墅窗户");
    }

    void buildFloor() override {
        house->setFloor("别墅地板");
    }

    std::shared_ptr<House> getHouse() override {
        return house;
    }

    void viewHouse() const override {
        std::cout << "这是一座好别墅,有" << house->getWall() << ", 有" << house->getWindow() << ", 有" << house->getDoor() << ", 有" << house->getFloor() << "!" << std::endl;
    }

private:
    std::shared_ptr<House> house;
};

class FlatBuilder : public Builder {
public:
    FlatBuilder() : house(std::make_shared<House>()) {}

    void buildWall() override {
        house->setWall("公寓墙");
    }

    void buildDoor() override {
        house->setDoor("公寓门");
    }

    void buildWindow() override {
        house->setWindow("公寓窗户");
    }

    void buildFloor() override {
        house->setFloor("公寓地板");
    }

    std::shared_ptr<House> getHouse() override {
        return house;
    }

    void viewHouse() const override {
        std::cout << "这是一座好公寓,有" << house->getWall() << ", 有" << house->getWindow() << ", 有" << house->getDoor() << ", 有" << house->getFloor() << "!" << std::endl;
    }

private:
    std::shared_ptr<House> house;
};

// 设计师
class Director {
public:
    Director(std::shared_ptr<Builder> builder) : builder(builder) {}

    void constructHouse() {
        builder->buildWall();   // 先建墙
        builder->buildWindow(); // 然后建窗户
        builder->buildDoor();   // 再建门
        builder->buildFloor();  // 最后建地板
    }

    void viewHouse() const {
        builder->viewHouse();
    }

private:
    std::shared_ptr<Builder> builder;
};

// 设计师请工程队按照图纸建造好房子(客户端)
void doWorking() {
    // 请一个建造别墅的工程队
    std::shared_ptr<Builder> builder = std::make_shared<VillaBuilder>();
    Director director(builder);
    director.constructHouse();
    director.viewHouse();

    // 请一个建造公寓的工程队
    builder = std::make_shared<FlatBuilder>();
    Director anotherDirector(builder);
    anotherDirector.constructHouse();
    anotherDirector.viewHouse();
}

int main() {
    // 开工
    doWorking();
    return 0;
}

运行效果

  1. 产品(Product)

    产品是最终构建出来的复杂对象,它包含多个组成部分和属性。产品类通常有多个子类,具体实现可以因业务需求而异。

  2. 建造者(Builder)

    建造者接口定义了构建产品的各个部分的方法。每个具体的建造者实现这些方法,按照特定的步骤来构建产品。

  3. 具体建造者(ConcreteBuilder)

    具体建造者实现了建造者接口,负责具体的构建步骤。这些步骤包括创建产品的不同部分,并在最后将产品返回。

  4. 指挥者(Director)

    指挥者类负责按照特定的顺序调用建造者的方法来构建产品。它将建造者的具体实现与构建过程分开,使得构建过程与产品的具体类型解耦。

  5. 客户端(Client)

    客户端负责使用指挥者和建造者来构建产品。客户端通常不需要知道产品的具体构建过程或其组成部分。

四、总结

建造者模式模仿建筑行业的建造行为,设计师设计好图纸交给工程队,工程队根据图纸建造房子,房子建造好之后交给客户。设计的代码中将构造(设计师的图纸)和表示(工程队造的房子)完美分离,这样可以把复杂的部分简单化,最后有机地组合在一起最终形成我们想要的产品。

相关推荐
南东山人40 分钟前
一文说清:C和C++混合编程
c语言·c++
Ysjt | 深3 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
ephemerals__3 小时前
【c++丨STL】list模拟实现(附源码)
开发语言·c++·list
Microsoft Word4 小时前
c++基础语法
开发语言·c++·算法
一只小小汤圆4 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
legend_jz4 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
嘿BRE5 小时前
【C++】几个基本容器的模拟实现(string,vector,list,stack,queue,priority_queue)
c++
ö Constancy6 小时前
c++ 笔记
开发语言·c++
fengbizhe6 小时前
笔试-笔记2
c++·笔记