还是让我们生产车模 , 奔驰和宝马, . 这回额外增加了一个新的需求 , 那就是汽车的启动 , 停止 , 喇叭声音 , 引擎声音都是由客户自己控制 , 他想什么顺序就什么顺序 . 那我们还是按照模板类的方式完成(这里可以直接理解成一个汽车的模型有上述四种功能即可, 不用翻代码) . 然后 , 我们来模拟一下XX公司的要求 : 生产一个奔驰模型 , 要求跑的时候 , 先发动引擎 , 然后在挂挡启动 , 然后停下 , 不需要喇叭 . 这个很容器满足 , 通过场景类(Java , 或者可以理解成主函数)实现该需求 .
/*
*客户告诉XX公司 , 我们要这样一个模型, 然后XX公司就告诉我老大
*说是要这样一个模型 , 这样一个顺序 , 然后我就来制造
*/
//客户要求 , run() [run()是一个测试车模所有功能的成员方法]的时候先发动引擎
//启动起来
//开了一段就停下
//我们把这个顺序赋予奔驰车
benz.run();
我们组装了这样的一辆汽车,满足了xx公司的需求 . 但是想想我们的需求,汽车的动作执行顺序是要能够随意调整的 . 我们只满足了一个需求,还有下一个需求呀,然后是第二个宝马模型,只要启动、停止,其他的什么都不要;第三个模型,先喇叭,然后启动,然后停止;第四…直到把你逼疯为止,那怎么办? 我们就一个一个地来写场景类满足吗? 不可能的,那我们要想办法来解决这个问题,有了! 我们为每种模型产品模型定义一个建造者,你要啥顺序直接告诉建造者,由建造者来建造 .
定义 : 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 .
建造者模式的通用类图 :
在建造者模式中 , 有如下四个角色 :
代码实现 :
#include
#include
#include
//#include
using namespace std;
//建造者模式
#if 0
//汽车模板
class CarModel
{
protected:
virtual void start() = 0;
//能发动 , 还要能停下来 , 那才是真本事
virtual void stop() = 0;
//按喇叭会出声音 , 是滴滴叫 , 还是哔哔叫
virtual void alarm() = 0;
//引擎会轰隆隆地响 , 不响那是假的
virtual void engineBoom() = 0;
public:
void setSequence(vector<string> _sequence)
{
sequeue = _sequence;
}
//那模型应该会跑吧 , 别管是人推 , 还是电力驱动 , 总之要会跑
void run()
{
int len = sequeue.size();
for(int i = 0 ;i < len ;++i)
{
if(sequeue[i] == "start")
{
start();
}
else if(sequeue[i] == "stop")
{
stop();
}
else if(sequeue[i] == "alarm")
{
alarm();
}
else if(sequeue[i] == "engineBoom")
{
engineBoom();
}
}
}
private:
vector<string> sequeue;
};
//产品类 , 奔驰产品
class BenzModel : public CarModel
{
//独立业务处理
public:
void start() { cout<<"奔驰车跑起来是这个样子的..."<<endl; }
void stop() { cout<<"奔驰车应该这样停车..."<<endl; }
void alarm() { cout<<"奔驰车的喇叭声音是这个样子的..."<<endl; }
void engineBoom() { cout<<"奔驰车的引擎声音是这样的..."<<endl; }
};
//抽象建造者
class CarBuilder
{
//设置产品的不同部分 , 以获得不同的产品
//建造产品
public:
virtual void setSequence(vector<string> sequence) = 0;
virtual CarModel* getCarModel() = 0;
};
//具体建造者 , 奔驰车建造者
class BenzBuilder : public CarBuilder
{
//设置产品的零件
//产品类内的逻辑处理
//组建一个产品
public:
BenzBuilder()
{
benz = new BenzModel();
}
CarModel* getCarModel()
{
return benz;
}
void setSequence(vector<string> _sequence)
{
benz->setSequence(_sequence);
}
~BenzBuilder()
{
delete benz;
}
private:
BenzModel* benz;
};
//导演类
class Director
{
//构建不同的产品
//设置不同的零件 , 生产不同的产品
public:
Director(BenzBuilder* benz)
{
benzBuilder = benz;
}
/*
*A型奔驰 , 先发动引擎 , 然后启动 , 然后停止 , 没有喇叭
*/
void getABenzModel()
{
//清空容器 , 防止意想不到情况
sequence.clear();
sequence.push_back("engineBoom");
sequence.push_back("start");
sequence.push_back("stop");
benzBuilder->setSequence(sequence);
//得到benz* , 调用run()方法
benzBuilder->getCarModel()->run();
}
/*
*B型奔驰 , 先按下喇叭 , 然后发动引擎 , 然后启动 , 最后停止
*/
void getBBenzModel()
{
//清空容器 , 防止意想不到情况
sequence.clear();
sequence.push_back("alarm");
sequence.push_back("engineBoom");
sequence.push_back("start");
sequence.push_back("stop");
benzBuilder->setSequence(sequence);
//得到benz* , 调用run()方法
benzBuilder->getCarModel()->run();
}
private:
vector<string> sequence;
BenzBuilder* benzBuilder;
};
int main()
{
BenzBuilder* benz = new BenzBuilder();
Director director(benz);
director.getABenzModel();
cout<<"============================="<<endl;
director.getBBenzModel();
delete benz;
return 0;
}
#endif
建造者模式关注的是零件类型和装配工艺(顺序),这是它与工厂方法模式最大不同的地方,虽然同为创建类模式,但是注重点不同 .
已经不用扩展了 , 因为在例子中已经对建造者模式进行了扩展 , 引入了模板方法模式 . 请注意,建造者模式中还有一个角色没有说明,就是零件,建造者怎么去建造一个对象? 是零件的组装,组装顺序不同对象效能也不同,这才是建造者模式要表达的核心意义,而怎么才能更好地达到这种效果呢? 引人模板方法模式是一个非常简单而有效的办法 .
编者将之前的代码进行完善 , 又加入一个宝马车模的建造 , 大部分的代码都是相似的 , 在导演类中稍有不同 . 算是一个加深理解吧 . 代码如下 :
#include
#include
#include
//#include
using namespace std;
//建造者模式(完整例子)
#if 0
//汽车模板
class CarModel
{
protected:
virtual void start() = 0;
//能发动 , 还要能停下来 , 那才是真本事
virtual void stop() = 0;
//按喇叭会出声音 , 是滴滴叫 , 还是哔哔叫
virtual void alarm() = 0;
//引擎会轰隆隆地响 , 不响那是假的
virtual void engineBoom() = 0;
public:
void setSequence(vector<string> _sequence)
{
sequeue = _sequence;
}
//那模型应该会跑吧 , 别管是人推 , 还是电力驱动 , 总之要会跑
void run()
{
int len = sequeue.size();
for(int i = 0 ;i < len ;++i)
{
if(sequeue[i] == "start")
{
start();
}
else if(sequeue[i] == "stop")
{
stop();
}
else if(sequeue[i] == "alarm")
{
alarm();
}
else if(sequeue[i] == "engineBoom")
{
engineBoom();
}
}
}
private:
vector<string> sequeue;
};
//产品类 , 奔驰产品
class BenzModel : public CarModel
{
//独立业务处理
public:
void start() { cout<<"奔驰车跑起来是这个样子的..."<<endl; }
void stop() { cout<<"奔驰车应该这样停车..."<<endl; }
void alarm() { cout<<"奔驰车的喇叭声音是这个样子的..."<<endl; }
void engineBoom() { cout<<"奔驰车的引擎声音是这样的..."<<endl; }
};
//产品类 , 宝马产品
class BMWModel : public CarModel
{
//独立业务处理
public:
void start() { cout<<"宝马车跑起来是这个样子的..."<<endl; }
void stop() { cout<<"宝马车应该这样停车..."<<endl; }
void alarm() { cout<<"宝马车的喇叭声音是这个样子的..."<<endl; }
void engineBoom() { cout<<"宝马车的引擎声音是这样的..."<<endl; }
};
//抽象建造者
class CarBuilder
{
//设置产品的不同部分 , 以获得不同的产品
//建造产品
public:
virtual void setSequence(vector<string> sequence) = 0;
virtual CarModel* getCarModel() = 0;
};
//具体建造者 , 奔驰车建造者
class BenzBuilder : public CarBuilder
{
//设置产品的零件
//产品类内的逻辑处理
//组建一个产品
public:
BenzBuilder()
{
benz = new BenzModel();
}
CarModel* getCarModel()
{
return benz;
}
void setSequence(vector<string> _sequence)
{
benz->setSequence(_sequence);
}
~BenzBuilder()
{
delete benz;
}
private:
BenzModel* benz;
};
//具体建造者 , 宝马车建造者
class BMWBuilder : public CarBuilder
{
//设置产品的零件
//产品类内的逻辑处理
//组建一个产品
public:
BMWBuilder()
{
bmw = new BMWModel();
}
CarModel* getCarModel()
{
return bmw;
}
void setSequence(vector<string> _sequence)
{
bmw->setSequence(_sequence);
}
~BMWBuilder()
{
delete bmw;
}
private:
BMWModel* bmw;
};
//导演类
class Director
{
//构建不同的产品
//设置不同的零件 , 生产不同的产品
public:
Director(BenzBuilder* benz , BMWBuilder* bmw)
{
benzBuilder = benz;
bmwBuilder = bmw;
}
/*
*A型奔驰 , 先发动引擎 , 然后启动 , 然后停止 , 没有喇叭
*/
void getABenzModel()
{
//清空容器 , 防止意想不到情况
sequence.clear();
sequence.push_back("engineBoom");
sequence.push_back("start");
sequence.push_back("stop");
benzBuilder->setSequence(sequence);
//得到benz* , 调用run()方法
benzBuilder->getCarModel()->run();
}
/*
*B型奔驰 , 先按下喇叭 , 然后发动引擎 , 然后启动 , 最后停止
*/
void getBBenzModel()
{
//清空容器 , 防止意想不到情况
sequence.clear();
sequence.push_back("alarm");
sequence.push_back("engineBoom");
sequence.push_back("start");
sequence.push_back("stop");
benzBuilder->setSequence(sequence);
//得到benz* , 调用run()方法
benzBuilder->getCarModel()->run();
}
/*
*A型宝马 , 先按下喇叭 , 然后发动引擎 , 然后启动 , 最后停止
*/
void getABMWModel()
{
//清空容器 , 防止意想不到情况
sequence.clear();
sequence.push_back("alarm");
sequence.push_back("engineBoom");
sequence.push_back("start");
sequence.push_back("stop");
bmwBuilder->setSequence(sequence);
//得到benz* , 调用run()方法
bmwBuilder->getCarModel()->run();
}
/*
*B型宝马 , 先启动 , 最后停止
*/
void getBBMWModel()
{
//清空容器 , 防止意想不到情况
sequence.clear();
sequence.push_back("start");
sequence.push_back("stop");
bmwBuilder->setSequence(sequence);
//得到benz* , 调用run()方法
bmwBuilder->getCarModel()->run();
}
private:
vector<string> sequence;
BenzBuilder* benzBuilder;
BMWBuilder* bmwBuilder;
};
int main()
{
BenzBuilder* benz = new BenzBuilder();
BMWBuilder* bmw = new BMWBuilder();
Director director(benz,bmw);
director.getABenzModel();
cout<<"============================="<<endl;
director.getBBenzModel();
cout<<"============================="<<endl;
director.getABMWModel();
cout<<"============================="<<endl;
director.getBBMWModel();
delete benz;
delete bmw;
return 0;
}
#endif
大家也许会犯嘀咕,这个建造者模式和工厂模式非常相似,是的,非常相似,但是记住一点你就可以游刃有余地使用了:建造者模式最主要的功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了,通俗地说就是零件的装配,顺序不同产生的对象也不同 ; 而工厂方法则重点是创建,创建零件是它的主要职责,组装顺序则不是它关心的 .
<<设计模式之禅 第二版>>
<<设计模式>>