26.1 工厂方法模式 VS 建造者模式
26.1.1 按工厂方法建造超人
(1)产品:两类超人,成年超人和未成年超人。
(2)工厂:这里选择简单工厂
【编程实验】工厂方法建造超人
//创建型模式大PK——工厂方法和建造者模式 //实例:利用简单工厂创建的超人 #include <iostream> using namespace std; //***************************抽象产品接口********************* //超人接口 class ISuperMan { public: //每个超人都有特殊的技能 virtual void specialTalent() = 0; virtual ~ISuperMan(){} }; //*************************具体产品*********************** //成年超人 class AdultSuperMan : public ISuperMan { public: void specialTalent() { cout << "超人力大无穷" <<endl; } }; //未成年人超人 class ChildSuperMan : public ISuperMan { public: void specialTalent() { cout << "小超人的能力是刀枪不入、快速移动" <<endl; } }; //***********************简单工厂**************************** class SuperManFactory { public: static ISuperMan* createSuperMan(string type) { //根据输入参数产生不同的超人 if(type == "adult") { return new AdultSuperMan(); } else if (type == "child") { return new ChildSuperMan(); } else return NULL; } }; int main() { //模拟生产超人(注意从生产工厂里出来的产品(如adult)都是一个模 //样的,没有特殊的地方,这与后面的建造者模式有很大的不同) ISuperMan* sm = SuperManFactory::createSuperMan("child"); //展示一下超人的技能 sm->specialTalent(); delete sm; return 0; };
26.1.2 按建造者模式建造超人
(1)产品的三大组成部分:躯体、特殊技能、身份标记
(2)建造者:Builder。注意,与标准的建造者模式不同,这里的部件如何组装的过程由各个具体的建造者负责,而标准的作法是放到Director角色中去完成的。
//创建型模式大PK——工厂方法和建造者模式 //实例:利用建造者模式创建的超人 #include <iostream> using namespace std; //***************************辅助类********************* //超人的身驱 class Body { string body; public: string& getBody(){return body;} void setBody(string value) { body = value; } }; //特殊技能 class SpecialTalent { string specialTalent; public: string& getSpecialTalent(){return specialTalent;} void setSpecialTalent(string value) { specialTalent = value; } }; //超人的标志 class SpecialSymbol { string symbol; public: string& getSymbol(){return symbol;} void setSymbol(string value) { symbol = value; } }; //超人 class SuperMan { private: Body body; SpecialSymbol specialSymbol; SpecialTalent specialTalent; public: string& getBody(){return body.getBody();} void setBody(string value) { body.setBody(value); } string& getSpecialTalent(){return specialTalent.getSpecialTalent();} void setSepcialTalent(string value) { specialTalent.setSpecialTalent(value); } string& getSpecialSymbol(){return specialSymbol.getSymbol();} void setSpecialSymbol(string value) { specialSymbol.setSymbol(value); } virtual ~SuperMan(){} }; //*************************Builder角色*********************** //抽象建造者 class Builder { protected: SuperMan* superMan; public: Builder() { superMan = new SuperMan(); } //构建出超人的躯体 void setBody(string value) { superMan->setBody(value); } //构建出超人的特殊技能 void setSpecialTalent(string value) { superMan->setSepcialTalent(value); } //构建出超人的特殊标记 void setSpecialSymbol(string value) { superMan->setSpecialSymbol(value); } //构建出一个完整的超人 //超人的各个部件都准备好了,具体怎么组装由实现类来决定, //体现建造者模式将复杂对象的构建和表示分离的意图 virtual SuperMan* getSuperMan() = 0; virtual ~Builder() { delete superMan; } }; //成年超人建造者 class AdultSuperManBuilder :public Builder { public: SuperMan* getSuperMan() { //1.标准的建造者模式,建造过程是放在Director中进行装配的。 //2.建造者模式关注产品的各个部分,甚至构建顺序, // 即相同的部件,装配顺序不同,产生的结果也可能不同, // 这正是建造者模式的意图) superMan->setBody("强壮的躯体"); superMan->setSepcialTalent("会飞行"); superMan->setSpecialSymbol("胸前带S标记"); return superMan; } }; //未成年超人建造者 class ChildSuperManBuilder :public Builder { public: SuperMan* getSuperMan() { //建造过程 superMan->setBody("强壮的躯体"); superMan->setSepcialTalent("刀枪不入"); superMan->setSpecialSymbol("胸前带小S标记"); return superMan; } }; //导演类 class Director { private: static Builder* adultBuilder; static Builder* childBuilder; public: //本例中,以下函数只是一个空壳,而标准的建造者模式 //其部件的组装过程是在以下两部函数中完成的! //建造一个成人超人 static SuperMan* getAdultSuperMan() { return adultBuilder->getSuperMan(); } //建造一个未成年人超人 static SuperMan* getChildSuperMan() { return childBuilder->getSuperMan(); } }; Builder* Director::adultBuilder = new AdultSuperManBuilder(); Builder* Director::childBuilder = new ChildSuperManBuilder(); int main() { //建造一个超人 SuperMan* sm = Director::getAdultSuperMan(); //SuperMan* sm = Director::getChildSuperMan(); //展示一个超人的能力 cout << "超人的身体:" << sm->getBody() << endl; cout << "超人的特殊能力:" << sm->getSpecialTalent() << endl; cout << "超人带的标志:" << sm->getSpecialSymbol() << endl; return 0; }; /*输出结果 超人的身体:强壮的躯体 超人的特殊能力:会飞行 超人带的标志:胸前带S标记 */
26.1.3 最佳实践
(1)意图不同
①工厂方法模式,关注的是一个产品整体,无须关心产品各部分是如何创建出来的。
②建造者模式,一个具体产品的产生是依赖各个部件的产生以及装配顺序,它关注的是“由零件一步一步地组装出产品对象”
③简单理解,工厂模式是一个对象创建的粗线条应用,建造者模式则是通过细线程勾勒出一个复杂对象,关注的是产品组成部分的创建过程。
(2)产品的复杂度不同
①工厂方法模式创建的产品一般都是单一性质产品,都是一个模样。
②建造者模式创建的则是一个复合产品,它则各个部件复合而成,部件不同,产品对象当然不同。
③一般来说工厂方法模式创建的产品的粒度比较粗,而建造者模式的产品对象粒度比较细。
(3)方法的选择:如果关注一个产品部件的生产、安装步骤,则选择建造者,否则选择工厂方法模式。
26.2 抽象工厂模式 VS 建造者模式
26.2.1 抽象工厂模式
(1)产品等级:宝马(BWM)、奔驰(Benz)
(2)产品族:即车型(如商务车型Van、运动型SUV),即每个工厂要生产两种车型
【编程实验】按抽象工厂模式生产车辆
//创建型模式大PK——抽象工厂方法和建造者模式 //实例:利用抽象工厂方法生产汽车 #include <iostream> using namespace std; //抽象产品 class ICar { public: //获取汽车生产商,即品牌 virtual string getBand() = 0; //获取汽车的型号 virtual string getModel() = 0; }; //抽象宝马车 class AbsBMW : public ICar { string BMW_BNAD; public: AbsBMW() { BMW_BNAD = "宝马汽车"; } string getBand() { return BMW_BNAD; } }; //宝马商务车 class BMWVan :public AbsBMW { string SEVENT_SEARIES; public: BMWVan():AbsBMW() { SEVENT_SEARIES = "7系列商务车"; } string getModel() { return SEVENT_SEARIES; } }; //宝马Suv class BMWSuv :public AbsBMW { string X_SEARIES; public: BMWSuv():AbsBMW() { X_SEARIES = "x系列Suv"; } string getModel() { return X_SEARIES; } }; //抽象奔驰车 class AbsBenz : public ICar { string BENZ_BNAD; public: AbsBenz() { BENZ_BNAD = "奔驰汽车"; } string getBand() { return BENZ_BNAD; } }; //奔驰商务车 class BenzVan :public AbsBenz { string R_SEARIES; public: BenzVan():AbsBenz() { R_SEARIES = "R系列商务车"; } string getModel() { return R_SEARIES; } }; //奔驰Suv class BenzSuv :public AbsBenz { string G_SEARIES; public: BenzSuv():AbsBenz() { G_SEARIES = "G系列Suv"; } string getModel() { return G_SEARIES; } }; //抽象工厂 class CarFactory { public: //生产SUV型 virtual ICar* createSuv() = 0; //生产商务车型 virtual ICar* createVan() = 0; }; //宝马车工厂 class BMWFactory : public CarFactory { public: ICar* createSuv() { return new BMWSuv(); } ICar* createVan() { return new BMWVan(); } }; //奔驰车工厂 class BenzFactory : public CarFactory { public: ICar* createSuv() { return new BenzSuv; } ICar* createVan() { return new BenzVan(); } }; int main() { //要求生产一辆奔驰车 cout <<"===要求生产一辆奔驰车SUV===" << endl; //首先找奔驰车的工厂 CarFactory* carFactory = new BenzFactory(); //开始生产 ICar* car = carFactory->createSuv(); //生产完毕,展示一下车辆信息 cout << "===车辆生产完毕,详细信息如下===" << endl; cout << "汽车品牌:" << car->getBand() <<endl; cout << "汽车型号:" << car->getModel() <<endl; return 0; }; /*输出结果 ===要求生产一辆奔驰车SUV=== ===车辆生产完毕,详细信息如下=== 汽车品牌:奔驰汽车 汽车型号:G系列Suv */
26.2.2 建造者模式
(1)整体:汽车。部分:引擎和车轮
(2)Builder:BenzBuilder和BMWBuilder
【编程实验】按建造者模式生产车辆
//创建型模式大PK——抽象工厂方法和建造者模式 //实例:利用建造者模式生产汽车 #include <iostream> using namespace std; //**********************辅助类******************************* //生产蓝图(这个蓝图会交给Director,让他这个要求去生产汽车) class Blueprint { private: string wheel; //车轮的要求 string engine; //引擎的要求 public: string getWheel(){return wheel;} void setWheel(string value) { wheel = value; } string getEngine(){return engine;} void setEngine(string value) { engine = value; } }; //车辆产品 class ICar { public: //汽车车轮 virtual string getWheel() = 0; //汽车引擎 virtual string getEngine() = 0; //显示信号 virtual string toString() = 0; virtual ~ICar (){} }; //具体车辆 class Car : public ICar { private: string engine; //引擎 string wheel; //车轮 public: Car(string engine, string wheel) { this->engine = engine; this->wheel = wheel; } string getEngine() { return engine; } string getWheel() { return wheel; } //演示车辆信息 string toString() { return "车的轮子是:" + wheel + "\n车的引擎是:" + engine; } }; //抽象建造者 class CarBuilder { private: //ICar* car; //等建造的汽车 Blueprint* bp; //设计蓝图 protected: //只有具体的建造者才可以查看蓝图 Blueprint* getBlueprint(){return bp;} public: //接收一份设计蓝图 void setBlueprint(Blueprint* value) { bp = value; } //部件的构建 virtual string buildWheel() = 0; virtual string buildEngine() = 0; //按照顺序生产一辆车 Car* buildCar() { return new Car(buildEngine(),buildWheel()); } virtual ~CarBuilder(){} }; //宝马车建造车间 class BMWBuilder : public CarBuilder { public: string buildEngine() { //按车间主任(Director)手里的蓝图进行设计 return getBlueprint()->getEngine(); } string buildWheel() { //按车间主任(Director)手里的蓝图进行设计 return getBlueprint()->getWheel(); } }; //奔驰车建造车间 class BenzBuilder : public CarBuilder { public: string buildEngine() { //按车间主任(Director)手里的蓝图进行设计 return getBlueprint()->getEngine(); } string buildWheel() { //按车间主任(Director)手里的蓝图进行设计 return getBlueprint()->getWheel(); } }; //导演类:Director class Director { private: //持有建造者的引用 CarBuilder* bmwBuilder; CarBuilder* benzBuilder; public: Director() { bmwBuilder = new BMWBuilder(); benzBuilder = new BMWBuilder(); } //生产车辆 ICar* createCar(CarBuilder* carBuilder, string engine, string wheel) { //导演手中的蓝图 Blueprint bp; bp.setEngine(engine); bp.setWheel(wheel); carBuilder->setBlueprint(&bp); return carBuilder->buildCar(); } //生产奔驰SUV ICar* createBenzSuv() { return createCar(benzBuilder, "benz的引擎","benz的轮胎"); } //生产宝马商务 ICar* createBMWVan() { return createCar(bmwBuilder, "BMW的引擎","BMW的轮胎"); } //生产混合车型 ICar* createComplexCar() { return createCar(bmwBuilder, "BMW的引擎","benz的轮胎"); } ~Director() { delete benzBuilder; delete bmwBuilder; } }; int main() { //定义一个导演类 Director director; //生成一辆奔驰车SUV cout <<"===制造一辆奔驰SUV===" << endl; ICar* benzSuv = director.createBenzSuv(); cout << benzSuv->toString() << endl; cout <<"===制造一辆宝马商务车===" << endl; ICar* bmwVan = director.createBMWVan(); cout << bmwVan->toString() << endl; cout <<"===制造一辆混合车===" << endl; ICar* complexCar = director.createComplexCar(); cout << complexCar->toString() << endl; delete benzSuv; delete bmwVan; delete complexCar; return 0; }; /*输出结果 ===制造一辆奔驰SUV=== 车的轮子是:benz的轮胎 车的引擎是:benz的引擎 ===制造一辆宝马商务车=== 车的轮子是:BMW的轮胎 车的引擎是:BMW的引擎 ===制造一辆混合车=== 车的轮子是:benz的轮胎 车的引擎是:BMW的引擎 */
26.2.3 最佳实践
(1)抽象工厂模式只关心一个工厂到底生产了哪些产品,不关心具体怎么生产的。
(2)建造者模式要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新的产品。
(3)抽象工厂中使用“工厂”来描述产品的构建,它是一种更高层次看对象的构建,而建造者使用“车间”来描述,不同的车间完成不同的创建和装配任务,一个完整的汽车生产过程需要引擎制造车间、引擎装配车间的配合才能完成,它们配合的基础是设计蓝图,而这个蓝图掌握在车间主任(Director)手中,它给建造者车间什么蓝图就能生产什么产品,它更关心建造过程。
(4)相对来说,抽象工厂模式比建造者模式的尺度更大,它关注产品整体,而建造者模式关注的是构建过程。
(5)如果希望屏蔽对象的创建过程,只提供一个良好的封装,可以选择抽象工厂模式。如果在构件时通过不同的装配产生出新的对象,可以使用建造者模式。