前言
尊重原创,本系列文本解析部分主要基于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 模式强调的是为创建多个相互依赖的对象提供一个同一的接口。