案例: 用户需要建造一个别墅和一个民居。
将别墅和民居的组成都抽象为一个门,一个墙和一个地面,建造别墅时分别是建造”别墅的门”、”别墅的墙”、”别墅的地面”,建造民居时则分别是建造”民居的门”、”民居的墙”、”民居的地面”。最简单的实现为:
class House
{
public:
void setFloor(string floor) { m_floor = floor; } //建造地面
void setWall(string wall) { m_wall = wall; } //建造墙
void setDoor(string door) { m_door = door; } //建造门
void outFloor() { cout << m_floor << endl; }
void outWall() { cout << m_wall << endl; }
void outDoor() { cout << m_door << endl; }
private:
string m_floor;
string m_wall;
string m_door;
};
int main(void)
{
//用户自己建造别墅
House* ph1 = new House;
ph1->setDoor("villa door");
ph1->setWall("villa wall");
ph1->setFloor("villa floor");
ph1->outFloor();
ph1->outWall();
ph1->outDoor();
delete ph1;
//用户自己建造民居
House* ph2 = new House;
ph2->setWall("citizen wall");
ph2->setDoor("citizen door");
ph2->setFloor("citizen floor");
ph2->outFloor();
ph2->outWall();
ph2->outDoor();
delete ph2;
return 0;
}
这种写法,显然用户代码和对象的构造耦合性太强,①用户在构建对象时需要考虑构建的逻辑(先建造墙还是先建造门等),②一旦对象发生改变对用户影响太大。要实现被构建的对象和用户代码的解耦合,用户代码可以”请一支工程队来建造房子”:
class House
{
public:
void setFloor(string floor) { m_floor = floor; } //建造地面
void setWall(string wall) { m_wall = wall; } //建造墙
void setDoor(string door) { m_door = door; } //建造门
void outFloor() { cout << m_floor << endl; }
void outWall() { cout << m_wall << endl; }
void outDoor() { cout << m_door << endl; }
private:
string m_floor;
string m_wall;
string m_door;
};
//负责建造别墅的施工队
class VillaBuild
{
public:
VillaBuild() : m_house(new House) {}
void makeBulid() { buildDoor(); buildWall(); buildFloor(); }
void buildDoor() { m_house->setDoor("villa door"); }
void buildWall() { m_house->setWall("villa wall"); }
void buildFloor() { m_house->setFloor("villa floor"); }
House* getHouse() { return m_house; }
private:
House* m_house;
};
int main(void)
{
House* ph1 = new House;
VillaBuild* build = new Build; //请工程队建造别墅
build->makeBulid(); //执行建造房子操作
ph1 = build->getHouse();
ph1->outFloor();
ph1->outWall();
ph1->outDoor();
delete ph1;
delete build;
return 0;
}
上面代码可用下面UML表示:
VillaBuild类只能负责建造别墅,显然,我们需要对VillaBuild进行抽象:定义抽象基类Buileder,其派生类可以实例化为建造别墅的VillaBuilder施工队、建造民居的CitizenBuilder施工队等,但是注意,建造别墅和建造民居的逻辑(在这里体现为先建造门还是先建造墙等)肯定是不同的,所以需要再增加一个类–设计者,用于控制施工队的建造逻辑。UML图为:
这就是建造者模式,它由4个角色组成:
(1)Builder: 统一抽象接口,定义为产品(房子)创建各个部分的虚函数
(2)VillaBuild: 创建产品各个部分的具体实现
(3)Director: 调用Builder的接口对象中的函数,正确构建产品
(4)House: 即产品,表示被建造的复杂对象
建造者模型适用于将一个对象的构建和对象的使用进行分离的情景。(对象的构建就是要使得该对象可用所要进行的设置步骤,对象的使用即是对对象的正常使用)。
//房子(产品)
class House
{
public:
void setFloor(string floor) { m_floor = floor; } //建造地面
void setWall(string wall) { m_wall = wall; } //建造墙
void setDoor(string door) { m_door = door; } //建造门
void outFloor() { cout << m_floor << endl; }
void outWall() { cout << m_wall << endl; }
void outDoor() { cout << m_door << endl; }
private:
string m_floor;
string m_wall;
string m_door;
};
//施工队抽象类
class Builder
{
public:
virtual void buildDoor() = 0;
virtual void buildWall() = 0;
virtual void buildFloor() = 0;
virtual House* getHouse() = 0;
};
//建造别墅的施工队
class VillaBuild : public Builder
{
public:
VillaBuild() : m_house(new House) {}
void buildDoor() { m_house->setDoor("villa door"); }
void buildWall() { m_house->setWall("villa wall"); }
void buildFloor() { m_house->setFloor("villa floor"); }
House* getHouse() { return m_house; }
private:
House* m_house;
};
//建造民房的施工队
class CitizenBuilder : public Builder
{
public:
CitizenBuilder() : m_house(new House) {}
void buildDoor() { m_house->setDoor("citizen door"); }
void buildWall() { m_house->setWall("citizen wall"); }
void buildFloor() { m_house->setFloor("citizen floor"); }
House* getHouse() { return m_house; }
private:
House* m_house;
};
//设计师,负责指挥施工队
class Director
{
public:
Director(Builder* build) : m_build(build){}
void Construct()
{
m_build->buildWall();
m_build->buildFloor();
m_build->buildDoor();
}
private:
Builder* m_build;
};
int main(void)
{
Director *dir = NULL;
CitizenBuilder *cb = NULL;
House *ph = NULL;
//指定建造民房的施工队并交付设计师指挥
cb = new CitizenBuilder;
dir = new Director(cb);
dir->Construct(); //设计师指挥建造房子操作
ph = cb->getHouse();
ph->outFloor();
ph->outWall();
ph->outDoor();
delete cb;
delete dir;
delete ph;
return 0;
}