设计模式 之 建造者模式(C++)

发布于:2025-02-21 ⋅ 阅读:(12) ⋅ 点赞:(0)

设计模式 之 建造者模式(C++)

建造者模式概述

建造者模式的核心在于将复杂对象的构建过程与其表示分离开来,使得同样的构建过程能够创建出不同的表示形式。简单来说,就是把对象的创建过程拆分成多个步骤,每个步骤由具体的建造者类负责完成,最后由指挥者类来协调这些步骤,从而完成对象的构建。

建造者模式的结构

建造者模式主要包含以下四个关键角色:

  1. 产品(Product):这是我们最终要构建的复杂对象,包含了对象的各种属性和行为。
  2. 抽象建造者(Builder):定义了创建产品各个部件的抽象方法,以及返回产品的方法,为具体建造者类提供了统一的接口。
  3. 具体建造者(Concrete Builder):实现了抽象建造者接口,具体负责实现创建产品各个部件的方法,根据不同的需求构建出不同的产品。
  4. 指挥者(Director):负责安排复杂对象的构建顺序,调用建造者的方法来完成产品的构建过程。

C++ 实现建造者模式示例

示例设计思路:

建造者模式通过将复杂对象的构建过程分解为独立步骤(由抽象建造者定义),由指挥者控制构建流程,具体建造者实现各步骤的组件装配,最终实现产品构建过程与组件实现的解耦,使得相同构建流程能创建不同配置的产品。

下面示例通过Director指挥MacBookBuilder依次执行构建主板、显示器和操作系统(buildBoard(), buildDisplay(), buildOs())的标准化流程,将计算机组件的具体实现(如Mac OS系统配置)封装在建造者内部,使同一构建流程能通过更换不同建造者(如未来添加的WindowsBuilder)生成不同的计算机产品。

1. 产品类(Computer

#include<iostream>
#include <string>
#include <memory>

// 产品类:电脑,作为抽象基类
class Computer{
    public:
        // 构造函数
        Computer(){}

        // 设置主板信息
        void setBoard(const std::string& board_name){
            _board = board_name;
        }

        // 设置显示器信息
        void setDisplay(const std::string &displayer_name) { _displayer = displayer_name; }

        // 显示电脑配置信息
        void showParamate(){
            std::string param = "Computer: Paramater:\n";
            param += "\tBoard: " + _board + "\n";
            param += "\tDisplayer: " + _displayer + "\n";
            param += "\tOS: " + _os + "\n";
            std::cout << param << std::endl;
        }

        // 纯虚函数,用于设置操作系统,需由子类实现
        virtual void setOs() = 0;
    protected:
        std::string _board;     // 主板信息
        std::string _displayer; // 显示器信息
        std::string _os;        // 操作系统信息
};

// 具体产品类:MacBook,继承自 Computer
class MacBook: public Computer{
    public:
        // 实现基类的纯虚函数,设置操作系统为 Mac OS
        void setOs() override{
            _os = "Mac OS";
        }
};

Computer 类是我们要构建的电脑产品的抽象基类,包含了主板、显示器和操作系统三个重要属性。setBoardsetDisplay 方法用于设置主板和显示器的信息,showParamate 方法用于显示电脑的配置信息,setOs 是一个纯虚函数,需要由具体的子类实现。MacBook 类继承自 Computer 类,实现了 setOs 方法,将操作系统设置为 Mac OS

2. 抽象建造者类(Builder

// 抽象建造者类,定义构建电脑各部件的抽象方法
class Builder{
    public:
        // 抽象方法:构建主板
        virtual void buildBoard(const std::string& board_name) = 0;

        // 抽象方法:构建显示器
        virtual void buildDisplay(const std::string& displayer_name) = 0;

        // 抽象方法:构建操作系统
        virtual void buildOs() = 0;

        // 抽象方法:返回构建好的电脑对象
        virtual std::shared_ptr<Computer> build() = 0;
};

Builder 是一个抽象类,定义了构建电脑各个部件的抽象方法 buildBoardbuildDisplaybuildOs,以及返回构建好的电脑对象的方法 build。具体建造者类需要实现这些抽象方法。

3. 具体建造者类(MacBookBuilder

// 具体建造者类:负责构建 MacBook 电脑
class MacBookBuilder: public Builder{
    public:
        // 构造函数,创建一个新的 MacBook 对象
        MacBookBuilder()
        :_computer(new MacBook()){}

        // 实现抽象方法:构建主板
        void buildBoard(const std::string& board_name){
            _computer->setBoard(board_name);
        }

        // 实现抽象方法:构建显示器
        void buildDisplay(const std::string& displayer_name){
            _computer->setDisplay(displayer_name);
        }

        // 实现抽象方法:构建操作系统
        void buildOs(){
            _computer->setOs();
        }

        // 实现抽象方法:返回构建好的电脑对象
        std::shared_ptr<Computer> build(){
            return _computer;
        }

    private:
        std::shared_ptr<Computer> _computer; // 存储构建中的电脑对象
};

MacBookBuilderBuilder 的具体实现类,负责构建 MacBook 电脑。在构造函数中创建一个新的 MacBook 对象,然后在 buildBoardbuildDisplaybuildOs 方法中分别为电脑设置具体的主板、显示器和操作系统信息。build 方法返回构建好的电脑对象。

4. 指挥者类(Director

// 指挥者类,负责安排电脑的构建顺序
class Director {
    public:
        // 构造函数,接收一个 Builder 指针
        Director(Builder* builder):_builder(builder){}

        // 按照顺序调用建造者的方法来构建电脑
        void construct(const std::string& board_name, const std::string& displayer_name)
            {
                _builder->buildBoard(board_name);
                _builder->buildDisplay(displayer_name);
                _builder->buildOs();
            }
    private:
        std::shared_ptr<Builder> _builder; // 存储建造者对象
};

Director 类负责安排电脑的构建顺序。在构造函数中接收一个 Builder 类型的指针,然后在 construct 方法中按照一定的顺序调用建造者的方法来构建电脑。

5. 客户端代码(main 函数)

int main(){
    // 创建一个 MacBook 建造者对象
    Builder* builder = new MacBookBuilder();

    // 创建指挥者对象,并传入建造者指针
    std::unique_ptr<Director> director(new Director(builder));

    // 指挥者开始构建电脑,传入主板和显示器信息
    director->construct("主板1", "显示器1");

    // 通过建造者获取构建好的电脑对象
    std::shared_ptr<Computer> computer = builder->build();

    // 显示电脑的配置信息
    computer->showParamate();

    return 0;
}

main 函数中,首先创建一个 MacBookBuilder 对象,然后将其传递给 Director 对象。调用 Directorconstruct 方法开始构建电脑,传入主板和显示器的信息。最后通过建造者的 build 方法获取构建好的电脑对象,并调用其 showParamate 方法显示电脑配置信息。

建造者模式的优缺点

优点

  • 分离构建与表示:将对象的构建过程和表示分离,使得构建过程更加清晰,易于维护和扩展。
  • 创建不同表示的对象:可以方便地创建不同类型的产品,只需要更换具体的建造者类即可。
  • 符合单一职责原则:每个建造者类只负责构建产品的一部分,职责明确,提高了代码的可维护性。

缺点

  • 增加系统复杂度:需要创建多个类(产品类、抽象建造者类、具体建造者类和指挥者类),增加了系统的复杂度。
  • 不适用于简单对象:对于简单对象的构建,使用建造者模式可能会显得过于繁琐。

建造者模式的适用场景

  • 对象构建过程复杂:当一个对象的构建需要多个步骤,并且每个步骤都有不同的实现方式时,可以使用建造者模式。例如,创建一个汽车对象,需要依次安装发动机、轮胎、座椅等部件,每个部件的安装方式可能不同。
  • 需要创建不同表示的对象:如果需要使用相同的构建过程来创建不同表示的对象,可以使用建造者模式。例如,创建不同配置的电脑,只需要更换具体的建造者类即可。

与其他模式的比较

与工厂模式的比较

工厂模式主要关注的是对象的创建,它隐藏了对象创建的细节,客户端只需要调用工厂方法即可获取对象。而建造者模式不仅关注对象的创建,还关注对象的构建过程,它将构建过程分解为多个步骤,通过指挥者来协调这些步骤的执行。

与抽象工厂模式的比较

抽象工厂模式主要用于创建一系列相关的对象,它返回的是一个产品族。而建造者模式主要用于创建一个复杂的对象,它通过多个步骤来构建这个对象。

工厂模式主要关注的是对象的创建,它隐藏了对象创建的细节,客户端只需要调用工厂方法即可获取对象。而建造者模式不仅关注对象的创建,还关注对象的构建过程,它将构建过程分解为多个步骤,通过指挥者来协调这些步骤的执行。

与抽象工厂模式的比较

抽象工厂模式主要用于创建一系列相关的对象,它返回的是一个产品族。而建造者模式主要用于创建一个复杂的对象,它通过多个步骤来构建这个对象。


网站公告

今日签到

点亮在社区的每一天
去签到