一、目的
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
这是Design Pattern里面对Builder的描述,可见Builder模式就是将制造产品的工序分离出来,通过工序的不同排列组合生产出不同的产品。Builder Pattern 和 Abstract Factory 以及 Factory Method 的区别是:Builder Pattern是对产品制造方法的抽象,比如TOTO生产不同马桶的工序抽象出来,用其中几道工序就可以生产不同的马桶;Factory Method是对工厂生产的产品的抽象,比如TOTO生产马桶,洗脸池以及浴缸,对这几种产品进行抽象就可以在TOTO的工厂里生产这一系列;Abstract Factory则是对工厂以及产品两者的抽象(见Abstract Factory 的例子)。二、模式产生动机
TOTO现在要生产座便器、小便器以及洗脸池,这几个产品的生产工序大致相同,因此可以提取出来成为一个工序流程。


这样,通过卫浴设备生产工序的不同组合我们就可以方便的生产者三种设备了。
三、适用性
1\每一个生产工序必须跟要生产的对象独立,没有耦合
2\工人生产的Construction必须可以满足不同产品的生产(既有不同的产品需要生产)
个人认为Builder模式可以被视为复杂化了的Simple Factory(创建了多个子产品,但最终组合到一起),但Builder模式的关键在于
在创建一个复杂对象时,其组合过程往往涉及复杂的处理,同时,这种职责的分离使得修改复杂对象的组合逻辑变得独立而简单。
四、结构
Builder(抽象生成器)角色:这个角色用来规范产品对象的各个组成成分的建造。一般而言,此角色独立于应用程序的商业逻辑。
Concrete Builder(具体生成器)角色:担任这个角色的是于应用程序紧密相关的类,它们在指导者的调用下创建产品实例。这个角色在实现抽象建造者角色提供的方法的前提下,达到完成产品组装,提供成品的功能。
Director(指导者)角色:调用具体建造者角色以创建产品对象。指导者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者对象。
Product(产品)角色:待创建的复杂对象。它要包含那些定义组件的类,包括将这些组件装配成产品的接口。
四、优缺点
职责分离,使程序的结构更加清晰,当需要提供新的产品时,只需要从Builder基类派生新的ConcreteBuilder类,在其
中实现新产品的创建工作,如果我们需要新的产品,或者调整新产品的创建过程,只需要对调用Builder类接口进行产品构建处的代码作简要修改即可,因为
产品各部分的构建过程已经封装在ConcreteBuilder类中了。
在Factory Method模式中,产品内部的表象是由产品自身来决定的;而在Builder模式中则是“外部化”为由Builder来负责。这样定义一个新的具体Builder角色就可以改变产品的内部表象,符合“开闭原则”。
Buider模式使得客户不需要知道太多产品内部的细节。它将复杂对象的创建和表示方式封装在一个具体的Builder角色中,并由Director来协调Builder角色来得到具体的产品实例。
Builder模式可以对复杂产品的创建进行更加精细的控制,产品的组成是由Director角色调用具体Builder角色来逐步完成的,所以比起其它创建型模式能更好的反映产品的构造过程。
五、扩展
在理解Builder模式时,有几点需要注意:
1、Builder模式与其它创建型模式一样,将产品的创建(Builder类系)与产品的使用分离(Client)开来,通过实现ConcreteBuilder来构建不同的产品;
2、
除了Builder类系,Builder模式中还存在一个重要的角色:Director。Director这个角色在Builder模式中常常被忽略,但
个人认为,Director对于我们理解和运用Builder模式有着重要作用,Builder及其子类负责产品各组成部分的创建,而Director负
责产品的组装,二者缺一不可(有些情况下,我们可以考虑将Director类的所担负的组装的职责移植到客户代码或Builder类中实现,虽然
Director的角色没有了,其功能仍然存在,但这样就失去了Director可扩展的优点);
3、
由于Builder模式将对象的组装从对象创建类系中分离出来,因此,可以通过向Director类传递不同的ConcreteBuilder,达到
“同样的构建过程可以创建不同的表示”,即同样的创建过程可以创建不同的产品的效果,这正是Builder模式的意义所在。
此外,除了在
Builder类系一方进行扩展,我们也可以在Director类系一方对Builder模式进行扩展,扩展成有多个ConcreteDirector的
情况,每个ConcreteDirector负责完成一种组装产品的方式,如ConcreteDirector1使用builder
.BuildPartA
+ builder
.BuildPartB来组装产品,而ConcreteDirector2使用builder
.BuildPartA
+ builder
.BuildPartC来组装产品,从而实现更加复杂的“产品生产线”。
六、实现
代码:
Builder.h
#ifndef BUILDER_H_HEADER_INCLUDED_B86938E4
#define BUILDER_H_HEADER_INCLUDED_B86938E4
//##ModelId=4796AB010350
class Builder
{
private:
std::auto_ptr<Builder> pBuilder;
public:
//##ModelId=4796CAA801D3
virtual void ModelCreate() = 0;
//##ModelId=4796CAD500B8
virtual void FireOn() = 0;
//##ModelId=4796CAFC03A4
virtual void Colorize() = 0;
//##ModelId=4796CABF0116
virtual void Assemble() = 0;
//##ModelId=4796CB1001AF
virtual void Package() = 0;
//##ModelId=4796D6850392
std::auto_ptr<Builder> GetProduct() {return pBuilder;}
};
#endif /* BUILDER_H_HEADER_INCLUDED_B86938E4 */
Director.h
#ifndef DIRECTOR_H_HEADER_INCLUDED_B8694D62
#define DIRECTOR_H_HEADER_INCLUDED_B8694D62
#include "Builder.h"
//##ModelId=4796AB030043
class Director
{
private:
//##ModelId=4796FCCC02D3
Builder* pBuilder;
public:
//##ModelId=4796D5020362
void Construction();
//##ModelId=4796FC1C015C
void setBuilder(Builder* builder) {pBuilder = builder;}
};
#endif /* DIRECTOR_H_HEADER_INCLUDED_B8694D62 */
Pistol.h
#ifndef PISTOL_H_HEADER_INCLUDED_B8691582
#define PISTOL_H_HEADER_INCLUDED_B8691582
#include "Builder.h"
//##ModelId=4796AABF017F
class Pistol : public Builder
{
public:
//##ModelId=4796D7360228
void ModelCreate();
//##ModelId=4796D73F019C
void FireOn();
//##ModelId=4796D744011F
void Colorize();
//##ModelId=4796D74C01BC
void Assemble();
//##ModelId=4796D74F00F1
void Package();
//##ModelId=4796D7530110
void ShowProduct();
};
#endif /* PISTOL_H_HEADER_INCLUDED_B8691582 */
Director.cpp
#include <iostream>
#include "Director.h"
#include "Builder.h"
using namespace std;
//##ModelId=4796D5020362
void Director::Construction()
{
pBuilder->ModelCreate();
pBuilder->FireOn();
pBuilder->Colorize();
pBuilder->Assemble();
pBuilder->Package();
}
Pistol.cpp
#include <iostream>
#include "Pistol.h"
using namespace std;
//##ModelId=4796D7360228
void Pistol::ModelCreate()
{
cout<<"ModelCreate"<<endl;
}
//##ModelId=4796D73F019C
void Pistol::FireOn()
{
cout<<"FireOn"<<endl;
}
//##ModelId=4796D744011F
void Pistol::Colorize()
{
cout<<"Colorize"<<endl;
}
//##ModelId=4796D74C01BC
void Pistol::Assemble()
{
cout<<"Assemble"<<endl;
}
//##ModelId=4796D74F00F1
void Pistol::Package()
{
cout<<"Package"<<endl;
}
//##ModelId=4796D7530110
void Pistol::ShowProduct()
{
cout<<"Pistol"<<endl;
}
main.cpp
#include <iostream>
#include <memory>
#include "Director.h"
#include "Builder.h"
#include "Pistol.h"
using namespace std;
void main( void )
{
//Builder* pBuilder = new Pistol();
//Director director;
//std::auto_ptr<Pistol> pistol;
//director.Construction(pBuilder);
//pistol = pBuilder->GetProduct();
//pistol->ShowProduct();
Pistol pistol;
Director director;
director.setBuilder(&pistol);
director.Construction();
pistol.GetProduct;
pistol.ShowProduct;
}