建造者模式(builder)
背景:kfc全国各地味道都一样。工作流程都是严格按照规定来的。新研发汉堡,做法相同,配料不同,只是加了一种具体的产品而已。
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。又叫生成器模式。该模式将产品的内部表现与产品的生产过程分隔开,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
如果使用了建造者模式,用户只需要指定需要建造的类型就可以得到它们,具体的建造过程和细节就不用知道。(画人,基类头脚手,设为虚基类,子类继承胖人,瘦人)
PersonDirector(指挥者),内有一个变量为PersonBuilder。根据用户的选择建造小人。
若新增高个矮个则根据需要确定是在基类,还是子类实现。即建造者类的方法应该足够普遍。
UML结构图
1.何时使用:主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临复杂的变化。
优点:使得建造代码与表示代码分离,建造者隐藏了该产品是如何实现的,所以若需要改变一个产品的内部表示,只需要在定义一个具体的建造者就可以了。
c++代码
//产品类 由多个部件组成
class Product {
private:
vector<string> m_parts;
public:
void add(string str) //添加产品部件
{
m_parts.push_back(str);
}
void show()
{
cout << "产品 :" << endl;
for (int i = 0; i < m_parts.size(); i++)
{
cout << m_parts.at(i) << endl;
}
cout << "+++++++++++++++" << endl;
}
};
//抽象建造者类,确定产品由两个部件 组成
class Builder {
public:
virtual void buildPartA() = 0; //设为虚基类,提示子类一定要重写,否则无法实例化
virtual void buildPartB() = 0;
virtual Product* getResult()=0; //得到产品建造后的方法
};
//具体建造者A
class ConcertBuilderA:public Builder{
public:
ConcertBuilderA()
{
m_product = new Product();
}
virtual void buildPartA()
{
m_product->add("PartA"); //建造具体的两个部件A和B
}
virtual void buildPartB()
{
m_product->add("PartB");
}
virtual Product* getResult()
{
return m_product;
}
private:
Product* m_product;
};
//具体建造者B
class ConcertBuilderB :public Builder {
public:
ConcertBuilderB()
{
m_product = new Product(); //写到初始化列表中有问题
}
virtual void buildPartA()
{
m_product->add("PartC"); //建造具体的两个部件C和D
}
virtual void buildPartB()
{
m_product->add("PartD");
}
virtual Product* getResult()
{
return m_product;
}
private:
Product* m_product;
};
//指挥者类,指挥建造过程
class Director {
public:
void construct(Builder* b)
{
b->buildPartA();
b->buildPartB();
}
};
int main()
{
//客户端不需要具体的建造过程
Director* d = new Director;
Builder* b1 = new ConcertBuilderA();
Builder* b2 = new ConcertBuilderB();
d->construct(b1); //指挥者用ConcertBuilderA的方法来建造产品
Product* p1 = b1->getResult();
p1->show();
d->construct(b2); //指挥者用ConcertBuilderA的方法来建造产品
Product* p2 = b2->getResult();
p2->show();
}
建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。(即若不重写,漏了什么,编译一定不通过,做饭不放盐一定不可以)
可以通过一定的设计结构(纯虚函数),提醒后面的一定要重写,否则无法编译。