一、建造者模式
建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。如建房子的过程有打地基、筑墙、安装门窗等,但是可以按照用户的不同需求进行建造不同风格的房子。
1.1 建造者模式的结构
抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;
具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造方法和装配方法,并返回创建结果。
产品(Product):具体的产品对象
指挥者(Director): 构建一个使用Builder接口的对象,安排复杂对象的构建过程,客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程。
1.2 建造者模式的实例
造房子:
二、代码
2.1 头文件
(1)定义产品类House类,具有florr、wall和root三个属性。
(2)定义2个抽象构造者AbstractBuilder,其构造函数即要new一个House实例对象,然后还有4个建墙、建地板等的纯虚函数。在后面的具体建造者类中重写纯虚函数。
(3)定义指挥者类Director类,这个类最重要也是最有挑战性的。含有抽象建造者对象AbstractBuilder、封装组装流程的House型方法(结果返回建造的结果)、setBuilder方法也是最有意思的(参数是AbstractBuilder *iBuilder,但我们是可以传入子类对象指针的,比如具体建造者A的对象指针,即用了多态)。
#include<string> using namespace std; //产品类House class House{ public: //构造函数 House(){} void setFloor(string iFloor){ this->floor = iFloor; } void setWall(string iWall){ this->wall = iWall; } void setRoof(string iRoof){ this->roof = iRoof; } //打印House信息 void printfHouseInfo(){ printf("Floor:%s\t\n", this->floor.c_str()); printf("Wall:%s\t\n", this->wall.c_str()); printf("Roof:%s\t\n", this->roof.c_str()); } private: string floor; string wall; string roof; }; //抽象建造者AbstractBall class AbstractBuilder{ public: AbstractBuilder(){ house = new House(); } //抽象方法: virtual void buildFloor() = 0; virtual void buildWall() = 0; virtual void buildRoof() = 0; //纯虚函数,在具体建造者中进行 virtual House *getHouse() = 0; //实例化房子类house对象 House *house; }; //具体建造者ConcreteBuilderA class ConcreteBuilderA :public AbstractBuilder{ public: ConcreteBuilderA(){ printf("ConcreteBuilderA\n"); } //具体实现方法 void buildFloor(){ this->house->setFloor("Floor_A"); } void buildWall(){ this->house->setWall("Wall_A"); } void buildRoof(){ this->house->setRoof("Roof_A"); } House *getHouse(){ return this->house; } }; //具体建造者ConcreteBuilderB class ConcreteBuilderB :public AbstractBuilder{ public: ConcreteBuilderB(){ printf("ConcreteBuilderB\n"); } //具体实现方法 void buildFloor(){ this->house->setFloor("Floor_B"); } void buildWall(){ this->house->setWall("Wall_B"); } void buildRoof(){ this->house->setRoof("Roof_B"); } House *getHouse(){ return this->house; } }; //指挥者Director class Director{ public: Director(){} //具体实现方法 void setBuilder(AbstractBuilder *iBuilder){ this->builder = iBuilder; } //封装组装流程,返回建造结果 House *construct(){ builder->buildFloor(); builder->buildWall(); builder->buildRoof(); return builder->getHouse(); } private: AbstractBuilder *builder; };
2.2 客户端代码
#include "BuilderPattern.h" int main(){ //抽象建造者 AbstractBuilder *builder; //指挥者 Director *director = new Director(); //产品:House House *house; //指定具体建造者A builder = new ConcreteBuilderA(); director->setBuilder(builder); house = director->construct(); house->printfHouseInfo(); //指定具体建造者B builder = new ConcreteBuilderB(); director->setBuilder(builder); house = director->construct(); house->printfHouseInfo(); system("pause"); return 0; }
在客户端只需要指定具体建造者,并作为参数传递给指挥者,通过指挥者即可得到结果。客户端无需关心House的建造方法和具体流程。
如果需要更换建造风格,只需要更换建造者即可。不同建造者之间木有联系,方便替换。
从代码优化角度来看,其实可以不需要指挥者Director的角色,而直接把construct方法放入具体建造者当中。