建造者模式(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;
}
代码解读
- 产品类(Car):这就是咱们要造的车,包括引擎、轮胎和车身。
- 抽象建造者类(CarBuilder):定义了如何一步步造车的接口。
- 具体建造者类(SportsCarBuilder 和 FamilyCarBuilder):具体实现了如何造运动型和家庭型汽车。
- 指挥者类(Director):负责指挥建造过程,让车一步步造出来。
- 客户端代码:先找个指挥官,然后让他指挥几个大牛技术员,把车造好展示出来。
优点
- 更好的控制:分步骤造车,可以精细控制每个部件的构建。
- 灵活性:可以用不同的建造者造出不同类型的车。
- 易于扩展:要增加新类型的车,只需添加一个新的具体建造者。
缺点
- 复杂性增加:多个建造者和指挥者类让系统复杂度增加。
- 不适用于简单对象:造个简单的小东西用这模式,未免有点大材小用。
通过建造者模式,你可以像个专业改装店老板一样,按自己的需求一步步打造出梦寐以求的座驾,是不是很带劲?
建造者模式的使用场景
1. 创建复杂对象
当对象的构建过程复杂且需要多个步骤时,建造者模式非常有用。它可以将复杂的构建过程拆分成多个简单的步骤。
示例: 在汽车制造过程中,需要安装引擎、轮胎和车身。每个步骤都可以由不同的具体建造者实现,构建不同类型的汽车(如运动型汽车和家庭型汽车)。
2. 对象的创建过程需要依赖于其组成部分的不同组合
当同一个创建过程可以创建不同表示的对象时,建造者模式非常适合。
示例: 一款游戏中的角色生成系统,玩家可以选择不同的角色属性(如武器、防具、技能),这些组合可以通过建造者模式来实现。
3. 构建过程中需要灵活应对变化
如果构建过程中的步骤和顺序可能会有所变化,使用建造者模式可以更灵活地控制构建过程。
示例: 在软件安装过程中,根据用户选择的组件和配置项,安装步骤可能会有所不同。建造者模式可以帮助灵活应对这些变化。
4. 需要隐藏复杂的构建过程
当对象的构建过程非常复杂,且不希望客户端直接了解构建的细节时,可以使用建造者模式。
示例: 在构建一个复杂的报表生成器时,生成报表的过程可能涉及多步数据处理和格式化,建造者模式可以将这些细节隐藏在建造者内部。
具体示例
为了更清晰地理解建造者模式的使用场景,我们结合前面的代码示例来说明:
假设你是一个汽车制造厂的老板,你的客户群体多种多样,有喜欢速度与激情的赛车迷,也有注重家庭实用性的温馨家庭。那么,你可以通过建造者模式来满足这些不同客户的需求。那么可以参考上方的示例。