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)如果希望屏蔽对象的创建过程,只提供一个良好的封装,可以选择抽象工厂模式。如果在构件时通过不同的装配产生出新的对象,可以使用建造者模式。