Bootstrap

设计模式之建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,用于分离一个复杂对象的构建和表示,使得同样的构建过程可以创建不同的表示。建造者模式通常用于构建那些由多个部分组成的复杂对象,比如汽车、房子、计算机等。想象一下,你要造一辆车,不同部件都得精心挑选,这时你就需要一个牛逼哄哄的建造者模式来帮你忙。建造者模式就像是个专业的汽车改装店,有个总设计师(Director)指挥,几位技术大牛(Builder)各司其职,最后整出一辆你梦寐以求的车。

UML类图

   +-------------------+
   |      Director     |
   +-------------------+
   | -builder: Builder*|
   +-------------------+
   | +construct()      |
   +-------------------+
            |
            |
            v
   +-------------------+
   |      Builder      |
   +-------------------+
   | +buildPartA()     |
   | +buildPartB()     |
   | +getResult()      |
   +-------------------+
            ^
            |
            |
   +-------------------------+
   |     ConcreteBuilder     |
   +-------------------------+
   | +buildPartA()           |
   | +buildPartB()           |
   | +getResult()            |
   +-------------------------+
            ^
            |
            |
   +-------------------+
   |      Product      |
   +-------------------+
   | -partA            |
   | -partB            |
   +-------------------+
   | +setPartA()       |
   | +setPartB()       |
   +-------------------+

示例代码

假设你要造两种车:运动型和家庭型。我们用建造者模式来实现。

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

// 产品类:汽车
class Car {
public:
    void setEngine(const std::string& engine) {
        engine_ = engine;
    }

    void setTires(const std::string& tires) {
        tires_ = tires;
    }

    void setBody(const std::string& body) {
        body_ = body;
    }

    void show() const {
        std::cout << "Car with " << engine_ << " engine, " 
                  << tires_ << " tires, and " << body_ << " body." << std::endl;
    }

private:
    std::string engine_;
    std::string tires_;
    std::string body_;
};

// 抽象建造者类
class CarBuilder {
public:
    virtual ~CarBuilder() = default;

    virtual void buildEngine() = 0;
    virtual void buildTires() = 0;
    virtual void buildBody() = 0;
    virtual std::unique_ptr<Car> getResult() = 0;
};

// 具体建造者类:运动型汽车建造者
class SportsCarBuilder : public CarBuilder {
public:
    SportsCarBuilder() {
        car_ = std::make_unique<Car>();
    }

    void buildEngine() override {
        car_->setEngine("V8");
    }

    void buildTires() override {
        car_->setTires("Racing");
    }

    void buildBody() override {
        car_->setBody("Sporty");
    }

    std::unique_ptr<Car> getResult() override {
        return std::move(car_);
    }

private:
    std::unique_ptr<Car> car_;
};

// 具体建造者类:家庭型汽车建造者
class FamilyCarBuilder : public CarBuilder {
public:
    FamilyCarBuilder() {
        car_ = std::make_unique<Car>();
    }

    void buildEngine() override {
        car_->setEngine("V6");
    }

    void buildTires() override {
        car_->setTires("Regular");
    }

    void buildBody() override {
        car_->setBody("Sedan");
    }

    std::unique_ptr<Car> getResult() override {
        return std::move(car_);
    }

private:
    std::unique_ptr<Car> car_;
};

// 指挥者类
class Director {
public:
    void setBuilder(CarBuilder* builder) {
        builder_ = builder;
    }

    void construct() {
        builder_->buildEngine();
        builder_->buildTires();
        builder_->buildBody();
    }

private:
    CarBuilder* builder_;
};

// 客户端代码
int main() {
	Director director;

	// 建造运动型汽车
	CarBuilder* sportsBuilder = new SportsCarBuilder; 
	director.setBuilder(sportsBuilder);
	director.construct();
	std::unique_ptr<Car> sportsCar = sportsBuilder->getResult();
	sportsCar->show();

	// 建造家庭型汽车
	CarBuilder* familyBuilder = new FamilyCarBuilder ;
	director.setBuilder(familyBuilder);
	director.construct();
	std::unique_ptr<Car> familyCar = familyBuilder->getResult();
	familyCar->show();

	return 0;
}

代码解读

  1. 产品类(Car):这就是咱们要造的车,包括引擎、轮胎和车身。
  2. 抽象建造者类(CarBuilder):定义了如何一步步造车的接口。
  3. 具体建造者类(SportsCarBuilder 和 FamilyCarBuilder):具体实现了如何造运动型和家庭型汽车。
  4. 指挥者类(Director):负责指挥建造过程,让车一步步造出来。
  5. 客户端代码:先找个指挥官,然后让他指挥几个大牛技术员,把车造好展示出来。

优点

  1. 更好的控制:分步骤造车,可以精细控制每个部件的构建。
  2. 灵活性:可以用不同的建造者造出不同类型的车。
  3. 易于扩展:要增加新类型的车,只需添加一个新的具体建造者。

缺点

  1. 复杂性增加:多个建造者和指挥者类让系统复杂度增加。
  2. 不适用于简单对象:造个简单的小东西用这模式,未免有点大材小用。

通过建造者模式,你可以像个专业改装店老板一样,按自己的需求一步步打造出梦寐以求的座驾,是不是很带劲?

建造者模式的使用场景

1. 创建复杂对象

当对象的构建过程复杂且需要多个步骤时,建造者模式非常有用。它可以将复杂的构建过程拆分成多个简单的步骤。

示例: 在汽车制造过程中,需要安装引擎、轮胎和车身。每个步骤都可以由不同的具体建造者实现,构建不同类型的汽车(如运动型汽车和家庭型汽车)。

2. 对象的创建过程需要依赖于其组成部分的不同组合

当同一个创建过程可以创建不同表示的对象时,建造者模式非常适合。

示例: 一款游戏中的角色生成系统,玩家可以选择不同的角色属性(如武器、防具、技能),这些组合可以通过建造者模式来实现。

3. 构建过程中需要灵活应对变化

如果构建过程中的步骤和顺序可能会有所变化,使用建造者模式可以更灵活地控制构建过程。

示例: 在软件安装过程中,根据用户选择的组件和配置项,安装步骤可能会有所不同。建造者模式可以帮助灵活应对这些变化。

4. 需要隐藏复杂的构建过程

当对象的构建过程非常复杂,且不希望客户端直接了解构建的细节时,可以使用建造者模式。

示例: 在构建一个复杂的报表生成器时,生成报表的过程可能涉及多步数据处理和格式化,建造者模式可以将这些细节隐藏在建造者内部。

具体示例

为了更清晰地理解建造者模式的使用场景,我们结合前面的代码示例来说明:

假设你是一个汽车制造厂的老板,你的客户群体多种多样,有喜欢速度与激情的赛车迷,也有注重家庭实用性的温馨家庭。那么,你可以通过建造者模式来满足这些不同客户的需求。那么可以参考上方的示例。

;