设计模式那点事--建造者模式
概念:
建造者模式(Builder)。将一个复杂对象的创建与它的表示分离,使得相同的构建过程能够创建不同的表示。
建造者模式能够将一个产品的内部表象与产品的生成过程切割开来,从而能够使一个建造过程生成具有不同的内部表象的产品对象。
我们仅仅需指定须要建造的类型就能够得到它们,而详细建造的过程和细节就不需知道了。
样例:
一个鲜活简单的样例总能让人轻松地理解晦涩的概念。我们来看看一个关于构建汽车的建造者模式。
我们知道。汽车一般由轮胎,引擎和车身组成。就像宝马(BMW)。法拉利(Ferrali)和奔驰(Benz)三辆汽车,它们也是由这三种东西组成的,仅仅只是构成模块价格不同。
对于它们来说。尽管组成模块价格不同,可是构建汽车都包括这三种东西,是一种公共操作。
于是。能够创建一个抽象父亲汽车构建类(CarBuilder),声明三个构建函数virtual void BuildWheel等的接口。
然后创建三个详细汽车构建子类:BMWBuilder,FerraliBuilder和BenzBuilder。用于详细汽车的构建,并提供返回详细汽车产品对象的接口。
它们分别继承于CarBuilder,每一个子类实现父类模块的个性化构建。
然后再定义一个构建汽车指导者CarDirector。用于控制汽车建造过程,隔离用户与建造过程的关联。最后定义一个产品类Product,用于显示终于的生成汽车产品。
角色:
1、建造者(Builder):为创建一个产品对象的各个部件指定抽象接口,如CarBuilder。
2、详细建造者(ConcreteBuilder):实现Builder的接口以构造和装配该产品的各个部件,定义并明白它所创建的表示,提供一个获取汽车成品对象的接口,如BMWBilder。
3、指示领导者(Director):构造一个使用Builder接口的对象,用于控制建造过程,隔离用户与建造过程的关联,如CarDirector。
4、详细产品(Product):表示被构造的复杂对象。如BMW汽车。
UML图:
代码:
#pragma warning(disable : 4786)
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//详细产品类
class Product
{
public:
vector<string> st;
public:
void AddParts(string sValue)
{
st.push_back(sValue);
}
void Show()
{
for (vector<string>::iterator stIter=st.begin(); stIter!=st.end(); stIter++)
{
cout<<*stIter<<endl;
}
}
};
//建造者类
class CarBuilder
{
public:
virtual void BuildWheel()
{
cout<<"CarBuilder:bulid wheel."<<endl;
}
virtual void BuildEngine()
{
cout<<"CarBuilder:bulid engine."<<endl;
}
virtual void BuildBody()
{
cout<<"CarBuilder:bulid body."<<endl;
}
};
//详细builder类,用于建造出详细产品
//实现CarBuilder的接口以构造和装配该产品的各个部件,定义并明白它所创建的表示,并 提供一个检索产品的接口
class BMWBuilder:public CarBuilder
{
public:
Product product;
public:
void BuildWheel()
{
product.AddParts("BMW:bulid wheel.");
}
void BuildEngine()
{
product.AddParts("BMW:bulid engine.");
}
void BuildBody()
{
product.AddParts("BMW:bulid body.");
}
Product GetProduct()
{
return product;
}
};
class FerraliBuilder:public CarBuilder
{
public:
Product product;
public:
void BuildWheel()
{
product.AddParts("Ferrali:bulid wheel.");
}
void BuildEngine()
{
product.AddParts("Ferrali:bulid engine.");
}
void BuildBody()
{
product.AddParts("Ferrali:bulid body.");
}
Product GetProduct()
{
return product;
}
};
class BenzBuilder:public CarBuilder
{
public:
Product product;
public:
void BuildWheel()
{
product.AddParts("Benz:bulid wheel.");
}
void BuildEngine()
{
product.AddParts("Benz:bulid engine.");
}
void BuildBody()
{
product.AddParts("Benz:bulid body.");
}
Product GetProduct()
{
return product;
}
};
//指挥者,用于控制建造过程,隔离用户与建造过程的关联
class CarDirector
{
private:
CarBuilder* cb;
public:
CarDirector(CarBuilder* cb)
{
this->cb = cb;
}
~CarDirector()
{
if (cb!=NULL)
{
delete cb;
cb = NULL;
}
}
void CreateCar()
{
cb->BuildWheel();
cb->BuildEngine();
cb->BuildBody();
}
};
int main()
{
int iTag=0;
Product product;
cout<<"----建造者模式開始----"<<endl;
cout<<"BMW:1,Ferrali:2,Benz:3"<<endl;
cout<<"请输入您想要构建的汽车:";
cin>>iTag;
if(iTag==1)
{
BMWBuilder* bb= new BMWBuilder;
CarDirector cd(bb);
cd.CreateCar();
product = bb->GetProduct();
product.Show();
}
else if(iTag==2)
{
FerraliBuilder* fb= new FerraliBuilder;
CarDirector cd(fb);
cd.CreateCar();
product = fb->GetProduct();
product.Show();
}
else if(iTag==3)
{
BenzBuilder* bb= new BenzBuilder;
CarDirector cd(bb);
cd.CreateCar();
product = bb->GetProduct();
product.Show();
}
cout<<"----建造者模式结束----"<<endl;
return 1;
}发散:
我们知道实现C++的多态有三种方法:函数重载,模板函数和虚函数。
虚函数实现的多态称为动态多态。上面代码有下面特点:
1、子类的对象转换给父类的对象如CarBuilder* cb= new BMWBuilder,我们称为向上转型。
它是安全的,自己主动完毕,而且会丢失子类型的信息;
2、为了解决子类型信息丢失的问题(子类对象转换给父类),父类必须实现了一个虚函数BuildWheel。
3、子类有全然同样的BuildWheel函数,覆盖重写父类的虚函数BuildWheel,这样便能实现动态多态了(否则仅仅能用指针或引用了)。
应用场景:
1、当创建一些复杂对象,这些对象内部构建间的建造顺序一般是稳定的。但对象内部的构建面临着复杂的变化;
2、当构造过程必须同意被构造的对象有不同表示时。
长处:
使得建造代码与表示代码分离,因为建造者隐藏了该产品是怎样组装的,所以若须要改变一个产品的内部表示。仅仅须要再定义一个详细的建造者就能够了,减少耦合性。

浙公网安备 33010602011771号