刚开始我一直感觉建造者模式不太好懂,也许是我笨了点缘故,勤能补拙嘛,所以只能多看多想了
大话设计模式里面那个对于建造者模式我讲解,个人感觉不太好理解,我是看了很多遍也没体会到那样设计的精髓,后来在另一本设计模式上才稍微领悟到了点,
在这里我想到一个比较形象的例子:
比如我某天去吃兰州拉面,他们有不同的套餐,套餐里包含的种类是一样的,都有一
碗拉面,一份泡菜,一杯饮料。但是不同的套餐里这3样又都不是全部一样的,也许分量和品质有差别。此时我们就可以用建造者模式。
这里我没有合适的UML图,大致说一下模型:客户根据套餐不同,跟收银员点了一份A套餐的拉面,另一名客户同时又点了一份B套餐的拉面,
这时收银员把这两个单子转交给后台,其实也就是厨房,厨师看到这两个单子的不同而煮不同的拉面,然后返回给服务员,服务员分发拉面给客户!
1.建造者(B u i l d e r)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。
2.具体建造者(Co n cre te B u i l d e r)角色:担任这个角色的是于应用程序紧密相关的类,它们在应用程序调用下创
建产品实例。
3.指导者(D i re cto r)角色:担任这个角色的类调用具体建造者角色以创建产品对象。是收银员,他知道我想要什么套餐,他会告诉里面的
店员工去准备什么套餐。
用代码实现如下:
class Food //定义产品类,指示拉面的一些属性
{
private:
vector<string> mFoodName;
vector<int> mPrice;
public:
void add(string foodName,int price)
{
mFoodName.push_back(foodName);
mPrice.push_back(price);
}
void show()
{
cout<<"food list:"<<endl;
cout<<"_______________________"<<endl;
for(int i=0;i<mFoodName.size();++i)
{
cout<<mFoodName[i]<<" "<<mPrice[i]<<endl;
}
}
};
class Builder //定义抽象的制作类,含有三个制作的环节和一个返回制作出来的产品方法
{
public:
virtual void BuildCoolDish() = 0;
virtual void BuildDrink() = 0;
virtual void BuildRice() = 0;
virtual Food* GetFood() = 0;
};
class BuilderA:public Builder //制作者A,我们假定他做出来的凉菜收20,饮料15,拉面25,总共60元,也就是说收银员接到60元的套餐就交给A来做
{
public:
BuilderA()
{
food = new Food();
}
virtual void BuildCoolDish()
{
cout<<"凉菜已经制作好,已加入制作工序容器(其实也就是做好了一样放在了盘子里)"<<endl;
food->add("CoolDish",20);
}
virtual void BuildDrink()
{
cout<<"饮料制作好了,已加入制作工序容器(放在了杯子里)"<<endl;
food->add("drink",15);
}
virtual void BuildRice()
{
cout<<"拉面做好了,放弃制作工序容器(放在了盘子里)"<<endl;
food->add("Rice",25);
}
virtual Food* GetFood()
{
return food;
}
private:
Food *food;
};
class BuilderB:public Builder //制作者B,我们假定他做出来的凉菜收30,饮料20,拉面20,总共70元,也就是说收银员接到70元的套餐就交给B来做
{
public:
BuilderB()
{
food = new Food();
}
virtual void BuildCoolDish()
{
cout<<"凉菜已经制作好,已加入制作工序容器(其实也就是做好了一样放在了盘子里)"<<endl;
food->add("CoolDish",30);
}
virtual void BuildDrink()
{
cout<<"饮料制作好了,已加入制作工序容器(放在了杯子里)"<<endl;
food->add("drink",20);
}
virtual void BuildRice()
{
cout<<"拉面做好了,放弃制作工序容器(放在了盘子里)"<<endl;
food->add("Rice",20);
}
virtual Food* GetFood()
{
return food;
}
private:
Food *food;
};
//定义收银员
class FoodManager
{
private:
Builder *builder;
public:
FoodManager(){builder = NULL;};
Food* FoodInfo(char ch)
{
if(ch == 'A')
builder = new BuilderA();
else if(ch == 'B')
builder = new BuilderB();
else
//你还可以加其他套餐;
;
builder->BuildCoolDish();
builder->BuildDrink();
builder->BuildRice();
return builder->GetFood();
}
};
int main()
{
FoodManager *p = new FoodManager();
char ch;
//客户到来,输入需要哪种套餐
for(int i=0;i<5;i++)
{
cin>>ch;
p->FoodInfo(ch)->show();
cout<<endl;
}
system("pause");
return 0;
}
这个例子在FoodManager的时候还利用了简单工厂模式,其实更好的设计可以把FoodManager改写成单例模式,因为一般一个收银员在指示其他所有的工作者听从她的指挥,好了,总结一下建造模式:
1、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的
细节。
2、每一个B u i l d e r都相对独立,而与其它的B u i l d e r无关。
3、可使对构造过程更加精细控制。
4、将构建代码和实现代码分开。
5、建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动
关于建造者模式的标准实例,相信学过C#的都知道有一个stringbuilder 他就是一个利用这种思想设计出来的,在我自己构思的C++库中我也会用string实作一个stringbuilder出来,到饭点了,闪!