前言

尊重原创,本系列文本解析部分主要基于Candidate for Master’s Degree School of Computer Wuhan University的K_Eckel([email protected])《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》。为了避免重造轮子,本系列博文对源码在ubuntu16.04下做了验证并上传到了gitee,再次感谢。

如有问题,可邮件联系我([email protected])并共同探讨解决方案。

目录

创建型模式(Creating Pattern)

Factory 模式 | AbstactFactory 模式 | Singleton 模式 | Builder 模式 | Prototype 模式

结构型模式(Structrual Pattern)

Bridge 模式 | Adapter 模式 | Decorator 模式 | Composite 模式 | Flyweight 模式 | Facade 模式 | Proxy 模式

行为型模式(Behavioral Pattern)

Template 模式 | Strategy 模式 | State 模式 | Observer 模式 | Memento 模式 | Mediator 模式 | Command 模式 | Visitor 模式 | Iterator 模式 | Interpreter 模式 | Chain of Responsibility 模式

Builder 模式简介:

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

假设一个场景:我们用一个类来表示车,车有一些必需的属性,比如:车身,轮胎,发动机,方向盘等。也有一些可选属性,假设超过10个,比如:车上的一些装饰,安全气囊等等非常多的属性。

问题

生活中有着很多的 Builder 的例子,个人觉得大学生活就是一个 Builder 模式的最好体现:要完成大学教育,一般将大学教育过程分成 4 个学年进行,因此学习可以看作是构建完整大学教育的一个部分构建过程,每个人经过这 4 年的(4 个阶段)构建过程得到的最后的结果不一样,因为可能在四个阶段的构建中引入了很多的参数(每个人的机会和际遇不完全相同)。

Builder 模式要解决的也正是这样的问题:当我们要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要把复杂对象的创建过程和这个对象的表示(展示)分离开来,这样做的好处就是通过一步步地进行复杂对象的构建,由于在每一步的构造过程中可以引入参数,使得经过相同的步骤创建最后得到的对象的展示不一样。

联想旗下有众多系列的电脑,例如:ThinkPad 和 Yoga。。。在科技创新的大潮下,产品层出不穷。电脑虽多,但结构基本一致,都是由 CPU、主板、内存、显卡等组成。如果为每台电脑都单独设计一个组装流程,管理的成本太高。这时,建造者模式就出现了,为所有系列指定一个统一的组装流程,所有的电脑都按照这个流程来组装。

模式选择

Builder 模式的典型结构图为:

图 1:Builder Pattern 结构图

Builder 模式的关键是其中的 Director 对象并不直接返回对象,而是通过一步步
(BuildPartA, BuildPartB, BuildPartC)来一步步进行对象的创建。当然这里 Director 可以提供一个默认的返回对象的接口(即返回通用的复杂对象的创建,即不指定或者特定唯一指定 BuildPart 中的参数)。

实现

完整代码示例(code)

Builder 模式的实现比较简单,这里为了方便初学者的学习和参考,将给出完整的实现代码(所有代码采用 C++实现,并在 Visual Studio Code,Version: 1.36.1 下测试运行)。

源码gitee地址:点击这里

代码目录结构:

patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Builder/src$ tree ../
../
├── include
│   ├── Builder.h
│   ├── Concrete_bulider.h
│   ├── Director.h
│   └── Product.h
└── src
    ├── Concrete_bulider.cpp
    ├── Director.cpp
    ├── main.cpp
    └── Product.cpp

2 directories, 8 files

Builder.h:

// Builder.h
#ifndef BUILDER_H
#define BUILDER_H

#include "Product.h"

// 建造者接口,组装流程
class IBuilder
{
public:
    virtual void BuildCpu() = 0;  // 创建 CPU
    virtual void BuildMainboard() = 0;  // 创建主板
    virtual void BuildRam() = 0;  // 创建内存
    virtual void BuildVideoCard() = 0;  // 创建显卡
    virtual Computer* GetResult() = 0;  // 获取建造后的产品
};

#endif // BUILDER_H

Concrete_bulider.h:

// Concrete_bulider.h
#ifndef CONCRETE_BULIDER_H
#define CONCRETE_BULIDER_H

#include "Builder.h"

// ThinkPad 系列
class ThinkPadBuilder : public IBuilder
{
public:
    ThinkPadBuilder();
    void BuildCpu();
    void BuildMainboard();
    void BuildRam();
    void BuildVideoCard();
    Computer* GetResult();

private:
    Computer *m_pComputer;
};

// Yoga 系列
class YogaBuilder : public IBuilder
{
public:
    YogaBuilder();
    void BuildCpu();
    void BuildMainboard();
    void BuildRam();
    void BuildVideoCard();
    Computer* GetResult();

private:
    Computer *m_pComputer;
};

#endif // CONCRETE_BULIDER_H

Director.h:

// Director.h
#ifndef DIRECTOR_H
#define DIRECTOR_H

#include "Builder.h"

// 指挥者
class Direcror
{
public:
    void Create(IBuilder *builder);
};

#endif // DIRECTOR_H

Product.h:

// Product.h
#ifndef PRODUCT_H
#define PRODUCT_H

#include <iostream>

using namespace std;

// 电脑
class Computer
{
public:
    void SetmCpu(string cpu);
    void SetmMainboard(string mainboard);
    void SetmRam(string ram);
    void SetVideoCard(string videoCard);

    string GetCPU();
    string GetMainboard();
    string GetRam();
    string GetVideoCard();

private:
    string m_strCpu;  // CPU
    string m_strMainboard;  // 主板
    string m_strRam;  // 内存
    string m_strVideoCard;  // 显卡
};

#endif // PRODUCT_H

Concrete_bulider.cpp:

// Concrete_bulider.cpp

#include "../include/Concrete_bulider.h"
#include <iostream>

using namespace std;

ThinkPadBuilder::ThinkPadBuilder() { m_pComputer = new Computer(); }
void ThinkPadBuilder::BuildCpu() { m_pComputer->SetmCpu("i5-6200U"); }
void ThinkPadBuilder::BuildMainboard() { m_pComputer->SetmMainboard("Intel DH57DD"); }
void ThinkPadBuilder::BuildRam() { m_pComputer->SetmRam("DDR4"); }
void ThinkPadBuilder::BuildVideoCard() { m_pComputer->SetVideoCard("NVIDIA Geforce 920MX"); }
Computer* ThinkPadBuilder::GetResult() { return m_pComputer; }

YogaBuilder::YogaBuilder() { m_pComputer = new Computer(); }
void YogaBuilder::BuildCpu() { m_pComputer->SetmCpu("i7-7500U"); }
void YogaBuilder::BuildMainboard() { m_pComputer->SetmMainboard("Intel DP55KG"); }
void YogaBuilder::BuildRam() { m_pComputer->SetmRam("DDR5"); }
void YogaBuilder::BuildVideoCard() { m_pComputer->SetVideoCard("NVIDIA GeForce 940MX"); }
Computer* YogaBuilder::GetResult() { return m_pComputer; }

Director.cpp:

// Director.cpp
#include <iostream>
#include "../include/Director.h"

using namespace std;

void Direcror::Create(IBuilder *builder) {
  builder->BuildCpu();
  builder->BuildMainboard();
  builder->BuildRam();
  builder->BuildVideoCard();
}

Product.cpp:

// Product.cpp

#include "../include/Product.h"
#include <iostream>

using namespace std;

void Computer::SetmCpu(string cpu) { m_strCpu = cpu; }
void Computer::SetmMainboard(string mainboard) { m_strMainboard = mainboard; }
void Computer::SetmRam(string ram) { m_strRam = ram; }
void Computer::SetVideoCard(string videoCard) { m_strVideoCard = videoCard; }

string Computer::GetCPU() { return m_strCpu; }
string Computer::GetMainboard() { return m_strMainboard; }
string Computer::GetRam() { return m_strRam; }
string Computer::GetVideoCard() { return m_strVideoCard; }

main.cpp:

// main.cpp
#include "../include/Concrete_bulider.h"
#include "../include/Director.h"
#include <string>

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif

int main()
{
    Direcror *pDirecror = new Direcror();
    ThinkPadBuilder *pTPBuilder = new ThinkPadBuilder();
    YogaBuilder *pYogaBuilder = new YogaBuilder();

    // 组装 ThinkPad、Yoga
    pDirecror->Create(pTPBuilder);
    pDirecror->Create(pYogaBuilder);

    // 获取组装后的电脑
    Computer *pThinkPadComputer = pTPBuilder->GetResult();
    Computer *pYogaComputer = pYogaBuilder->GetResult();

    // 测试输出
    cout << "-----ThinkPad-----" << endl;
    cout << "CPU: " << pThinkPadComputer->GetCPU() << endl;
    cout << "Mainboard: " << pThinkPadComputer->GetMainboard() << endl;
    cout << "Ram: " << pThinkPadComputer->GetRam() << endl;
    cout << "VideoCard: " << pThinkPadComputer->GetVideoCard() << endl;

    cout << "-----Yoga-----" << endl;
    cout << "CPU: " << pYogaComputer->GetCPU() << endl;
    cout << "Mainboard: " << pYogaComputer->GetMainboard() << endl;
    cout << "Ram: " << pYogaComputer->GetRam() << endl;
    cout << "VideoCard: " << pYogaComputer->GetVideoCard() << endl;

    SAFE_DELETE(pThinkPadComputer);
    SAFE_DELETE(pYogaComputer);
    SAFE_DELETE(pTPBuilder);
    SAFE_DELETE(pYogaBuilder);
    SAFE_DELETE(pDirecror);

    getchar();

    return 0;
}

代码说明

我们需要通过“Product.h”创建一个 Computer 类,它可以通过组装零件来创建。

产品类准备好以后,就可以通过“Builder.h”创建 Builder 类了,Builder 提供的功能用于创建电脑的各个部件。

有了 Builder 接口,接下来的事情就是通过“Concrete_bulider.h”让 ConcreteBuilder 对象到位。在这些建造者中,我们可以指定每台电脑要使用的部件信息。

最后,我们通过“Director.h”创建一个 Director 类,让 Create 方法接受一个 IBuilder,然后在内部调用相应的组装函数。

现在,一起来看看客户端“main.cpp”代码,可以看到创建任何产品都非常干净。

编译运行结果:

patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Builder/src$ g++ *.cpp -std=c++11
patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Builder/src$ ./a.out 
-----ThinkPad-----
CPU: i5-6200U
Mainboard: Intel DH57DD
Ram: DDR4
VideoCard: NVIDIA Geforce 920MX
-----Yoga-----
CPU: i7-7500U
Mainboard: Intel DP55KG
Ram: DDR5
VideoCard: NVIDIA GeForce 940MX

patten@patten-hp:~/workspace/others/cpp/designPatterns/creatingPattern/Bu/src$

讨论

GoF 在《设计模式》一书中给出的关于 Builder 模式的意图是非常容易理解、间接的:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示(在示例代码中可以通过传入不同的参数实现这一点)。

Builder 模式和 AbstractFactory 模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:Builder 模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说 Builder 模式中对象不是直接返回的。而在 AbstractFactory 模式中对象是直接返回的,AbstractFactory 模式强调的是为创建多个相互依赖的对象提供一个同一的接口。

致谢

一去丶二三里C++ 建造者模式