前言:
继续来聊一聊创建型设计模式:建造者模式;
前面还有聊过一些其他创建型模式,传送门如下:
工厂模式C++示例代码:简单工厂模式、工厂方法模式和抽象工厂模式-优快云博客
工厂模式:抽象工厂模式 C++代码实现、场景及优缺点-优快云博客
工厂模式:简单工厂知多少?原理、示例代码、场景及优缺点?-优快云博客
设计模式:C++如何实现一个高质量的单例模式,双重校验锁 懒汉多线程安全 ,还得考虑防止编译器优化、异常死锁-优快云博客
一、建造者模式原理及示例代码
建造者模式是一种创建型设计模式,它用于创建复杂对象。该模式允许您逐步构造一个对象,同时隐藏构造细节。这种模式特别适用于创建具有多个属性的对象,或者创建过程中涉及多个步骤的对象。
建造者模式通常由以下几个角色组成:
- 产品(Product):要创建的复杂对象。
- 抽象建造者(Builder):定义了创建产品各个部件的抽象接口。
- 具体建造者(ConcreteBuilder):实现了抽象建造者接口,负责具体的产品部件的创建。
- 指挥者(Director):负责使用建造者来构建产品对象。
下面是一个简单的C++源码实现建造者模式的示例:
#include <iostream>
#include <string>
// 产品类
class Pizza {
public:
void setDough(const std::string& dough) {
m_dough = dough;
}
void setSauce(const std::string& sauce) {
m_sauce = sauce;
}
void setTopping(const std::string& topping) {
m_topping = topping;
}
void open() const {
std::cout << "Pizza with " << m_dough << " dough, " << m_sauce << " sauce and " << m_topping << " topping. Mmm!" << std::endl;
}
private:
std::string m_dough;
std::string m_sauce;
std::string m_topping;
};
// 抽象建造者
class PizzaBuilder {
public:
virtual ~PizzaBuilder() {}
Pizza* getPizza() {
return m_pizza;
}
void createNewPizza() {
m_pizza = new Pizza();
}
virtual void buildDough() = 0;
virtual void buildSauce() = 0;
virtual void buildTopping() = 0;
protected:
Pizza* m_pizza;
};
// 具体建造者
class HawaiianPizzaBuilder : public PizzaBuilder {
public:
virtual void buildDough() override {
m_pizza->setDough("cross");
}
virtual void buildSauce() override {
m_pizza->setSauce("mild");
}
virtual void buildTopping() override {
m_pizza->setTopping("ham+pineapple");
}
};
class SpicyPizzaBuilder : public PizzaBuilder {
public:
virtual void buildDough() override {
m_pizza->setDough("pan baked");
}
virtual void buildSauce() override {
m_pizza->setSauce("hot");
}
virtual void buildTopping() override {
m_pizza->setTopping("pepperoni+salami");
}
};
// 指挥者
class Cook {
public:
void setPizzaBuilder(PizzaBuilder* pb) {
m_pizzaBuilder = pb;
}
Pizza* getPizza() {
return m_pizzaBuilder->getPizza();
}
void constructPizza() {
m_pizzaBuilder->createNewPizza();
m_pizzaBuilder->buildDough();
m_pizzaBuilder->buildSauce();
m_pizzaBuilder->buildTopping();
}
private:
PizzaBuilder* m_pizzaBuilder;
};
int main() {
Cook cook;
HawaiianPizzaBuilder hawaiianPizzaBuilder;
SpicyPizzaBuilder spicyPizzaBuilder;
cook.setPizzaBuilder(&hawaiianPizzaBuilder);
cook.constructPizza();
Pizza* hawaiianPizza = cook.getPizza();
hawaiianPizza->open();
cook.setPizzaBuilder(&spicyPizzaBuilder);
cook.constructPizza();
Pizza* spicyPizza = cook.getPizza();
spicyPizza->open();
delete hawaiianPizza;
delete spicyPizza;
return 0;
}
在这个示例中,Pizza
类是产品类,PizzaBuilder
是抽象建造者,HawaiianPizzaBuilder
和SpicyPizzaBuilder
是具体建造者,Cook
是指挥者。通过使用建造者模式,我们可以逐步构建不同类型的披萨对象,而不需要了解具体的构建细节。
二、结构图
建造者模式的结构图通常包括以下几个要素:
- 产品(Product):要创建的复杂对象。
- 抽象建造者(Builder):定义了创建产品各个部件的抽象接口。
- 具体建造者(ConcreteBuilder):实现了抽象建造者接口,负责具体的产品部件的创建。
- 指挥者(Director):负责使用建造者来构建产品对象。
下面是建造者模式的结构图示例:
+-------------------+ +------------------+
| Product | | Builder |
+-------------------+ +------------------+
| | | + createProduct()|
| | | + buildPartA() |
| | | + buildPartB() |
| | | + buildPartC() |
+---------+---------+ +--------+---------+
| |
| |
| |
| |
+---------+---------+ +--------+---------+
|ConcreteProduct | | ConcreteBuilder |
+-------------------+ +------------------+
| | | + buildPartA() |
| | | + buildPartB() |
| | | + buildPartC() |
+-------------------+ +--------+---------+
|
|
|
|
+-------+---------+
| Director |
+---------------+
| + construct() |
+---------------+
在这个结构图中,产品(Product)是要创建的复杂对象,抽象建造者(Builder)定义了创建产品各个部件的抽象接口。具体建造者(ConcreteBuilder)实现了抽象建造者接口,负责具体的产品部件的创建。指挥者(Director)负责使用建造者来构建产品对象。
三、使用场景
建造者模式通常适用于以下场景:
-
当创建复杂对象的构造过程需要独立于其表示时,可以使用建造者模式。这意味着构造过程可以有不同的表示,而客户端代码无需关心具体的构造细节。
-
当一个对象的构造过程具有多个步骤,并且不同的构造步骤可以产生不同的表示时,建造者模式是一个很好的选择。通过使用建造者模式,可以将构造过程的每个步骤进行解耦,以便可以灵活地组合这些步骤来构建不同的对象表示。
-
当需要创建的对象具有复杂的内部结构,但客户端代码只关心最终的产品对象时,建造者模式可以隐藏对象的内部构造细节,使客户端代码更加简洁。
-
当创建对象的过程中涉及到可选的部件时,可以使用建造者模式。建造者模式可以方便地处理可选部件的构造和组合,而不需要创建大量的构造方法重载。
总之,建造者模式适用于需要创建复杂对象,且希望将构造过程与表示分离的情况。它可以帮助我们更好地组织对象的构造过程,使得代码更加灵活、可维护和可扩展。
四:优缺点
建造者模式的优点包括:
-
分离构建过程和最终表示:建造者模式可以将一个复杂对象的构建过程与其最终表示分离开来,使得构建过程可以灵活地组合,而不会影响最终的产品表示。
-
容易扩展:由于建造者模式将构建过程解耦,因此可以比较容易地增加新的具体建造者,以及修改已有的具体建造者,而不会对客户端代码产生影响。
-
可以对构建过程进行精细控制:建造者模式允许您对构建过程的每个步骤进行精细的控制,从而可以更好地满足特定需求。
-
提高代码复用性:通过建造者模式,可以将构建过程的代码进行复用,从而避免了重复的构建代码,提高了代码的复用性。
建造者模式的缺点包括:
-
增加了系统的复杂度:引入了建造者模式后,系统会增加一些新的类,从而增加了系统的复杂度。
-
需要额外的开发工作:使用建造者模式需要定义抽象建造者、具体建造者等额外的类,这可能增加了一些额外的开发工作。
总的来说,建造者模式适用于需要构建复杂对象,且希望将构建过程与最终表示分离的情况。它可以提供灵活性、可扩展性和精细控制,但也需要权衡额外的复杂度和开发工作。