一、建造者模式说明
建造者模式(Builder Pattern)是一种创建型设计模式,它的主要目的是将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
在建造者模式中,通常涉及以下几个角色:
产品(Product):
- 产品是要构建的复杂对象,包含多个部件。
- 产品通常是由多个部件组成的复杂对象,建造者模式的目标就是创建这个复杂对象。
抽象建造者(Builder):
- 抽象建造者定义了创建产品各个部件的抽象接口。
- 抽象建造者中通常包含多个方法,用于构建产品的各个部件,例如构建引擎、构建轮胎、构建座椅等。
- 它可以是一个抽象类或接口。
具体建造者(Concrete Builder):
- 具体建造者实现了抽象建造者接口,负责具体构建产品的各个部件。
- 每个具体建造者类对应一个特定的产品类型,并定义了具体构建该产品的过程。
- 具体建造者类通常包含私有成员变量用于保存构建过程中的临时状态,并提供方法来构建不同部件。
指挥者(Director):
- 指挥者负责调用具体建造者的方法来构建产品。
- 指挥者知道构建产品的具体步骤和顺序,但不知道产品的具体细节。
- 指挥者根据客户端的需求调用具体建造者的方法,将产品的构建过程与表示分离。
二、建造者模式样例
#include <iostream>
#include <string>// 产品类
class Product {
public:void setPartA(const std::string& partA) {partA_ = partA;}void setPartB(const std::string& partB) {partB_ = partB;}void setPartC(const std::string& partC) {partC_ = partC;}void show() const {std::cout << "Product parts: " << partA_ << ", " << partB_ << ", " << partC_ << std::endl;}private:std::string partA_;std::string partB_;std::string partC_;
};// 抽象建造者类
class Builder {
public:virtual ~Builder() {}virtual void buildPartA() = 0;virtual void buildPartB() = 0;virtual void buildPartC() = 0;virtual Product getResult() = 0;
};// 具体建造者类A
class ConcreteBuilderA : public Builder {
public:void buildPartA() override {product_.setPartA("PartA by ConcreteBuilderA");}void buildPartB() override {product_.setPartB("PartB by ConcreteBuilderA");}void buildPartC() override {product_.setPartC("PartC by ConcreteBuilderA");}Product getResult() override {return product_;}private:Product product_;
};// 具体建造者类B
class ConcreteBuilderB : public Builder {
public:void buildPartA() override {product_.setPartA("PartA by ConcreteBuilderB");}void buildPartB() override {product_.setPartB("PartB by ConcreteBuilderB");}void buildPartC() override {product_.setPartC("PartC by ConcreteBuilderB");}Product getResult() override {return product_;}private:Product product_;
};// 指挥者类
class Director {
public:void construct(Builder& builder) {builder.buildPartA();builder.buildPartB();builder.buildPartC();}
};int main() {Director director;ConcreteBuilderA builderA;ConcreteBuilderB builderB;// 构建产品Astd::cout << "Product A:" << std::endl;director.construct(builderA);Product productA = builderA.getResult();productA.show();// 构建产品Bstd::cout << "\nProduct B:" << std::endl;director.construct(builderB);Product productB = builderB.getResult();productB.show();return 0;
}
三、建造者模式的场景
以下是一些适用建造者模式的具体场景:
游戏角色创建器:在游戏中,玩家可以选择不同的角色并自定义其外观、能力和装备。建造者模式可以用于创建角色的建造器,每个具体建造者负责构建不同类型的角色,而指挥者负责组装角色的各个部件,最终创建出完整的角色对象。
文档生成器:在文档生成器中,可能需要创建不同类型的文档,例如简历、报告、新闻稿等。建造者模式可以用于创建文档的建造器,每个具体建造者负责构建不同类型的文档,而指挥者负责组装文档的各个部件,最终生成所需的文档对象。
电脑组装器:在电脑组装器中,用户可以选择不同的硬件配置和外设,并自定义其性能和功能。建造者模式可以用于创建电脑的建造器,每个具体建造者负责构建不同配置的电脑,而指挥者负责组装电脑的各个部件,最终组装成用户所需的电脑。
汽车定制器:在汽车定制器中,用户可以选择不同的汽车型号、颜色、配置和附件。建造者模式可以用于创建汽车的建造器,每个具体建造者负责构建不同配置的汽车,而指挥者负责组装汽车的各个部件,最终定制成用户所需的汽车。
食品套餐订购系统:在食品套餐订购系统中,用户可以选择不同的食品套餐、主食、配菜和饮料。建造者模式可以用于创建食品套餐的建造器,每个具体建造者负责构建不同套餐的各个部件,而指挥者负责组装套餐的各个部件,最终生成用户所需的套餐对象。
四、建造者模式优缺点
建造者模式具有以下优点和缺点:
优点:
分离构建过程和表示:建造者模式将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示,提高了系统的灵活性。
隐藏构建细节:建造者模式将对象的构建过程封装起来,只向客户端暴露一个简单的构建接口,客户端不需要关心对象的构建细节,降低了客户端与具体构建过程的耦合度。
更加精细地控制构建过程:建造者模式可以让客户端按照需要灵活地指定构建顺序和选择构建部件,可以更加精细地控制对象的构建过程,满足不同的需求。
增加对象的可复用性:由于建造者模式将对象的构建过程封装起来,可以在不改变原有代码的情况下,通过新增具体建造者类来创建新的对象表示,提高了对象的可复用性。
增加系统的扩展性:由于建造者模式将构建过程和表示分离,新增具体建造者类或修改指挥者类不会影响其他部分的代码,增加了系统的扩展性。
缺点:
增加系统复杂度:建造者模式引入了多个角色和类,增加了系统的复杂度,可能会导致代码量增加,不利于理解和维护。
不适用于对象较简单的情况:当对象的构建过程比较简单,或者对象的内部结构比较稳定时,使用建造者模式可能会显得繁琐,不适合使用。
不利于组装顺序的灵活性:建造者模式将构建过程固化在建造者类中,可能会限制对象组装顺序的灵活性,如果需要改变组装顺序,则需要修改建造者类或指挥者类。
可能会产生多余的对象:由于建造者模式将构建过程和表示分离,可能会导致在构建对象过程中产生多余的对象,增加了系统的资源消耗。