[设计模式]创建模式-建造者(C++描述)
second60 20180426
1. 什么是建造者模式
当创建的对象很复杂,由多个其他对象组合而成时,我们要对复杂的对象的创建过程进行分离,通过一步一步来对复杂对象的构建,每一步构造过程可以引入参数,使得相同步骤创建最后得到不同的对象。
一句话总结:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象
解决的问题:
1. 创建复杂对象无须知道实现过程
2. 对象的构建过程和细节封装
2. 建造者模式图
模式讲解:
1. 指挥者(Director)类和客户沟通
2. 指挥者将创建产品的需求划分成备个部件的建造Builder
3. 各部件的建造委派到具体的建造者ConcreteBuilder
4. ConcreteBuilder负责产品的构建
5. 最终构建成具体的产品Product
3. 实例讲解
最晚就开始写建造者模型,今天一直在想,怎么来讲解比较好呢?以前虽然用进,但场景忘记是哪里出现过了。所以今天想了一天,想了个可以运用的实例。最近棋牌很火,就以棋牌为例。
在棋牌中,有很多的子游戏,如:麻将类,牌类,棋类。这里就以麻将类为例,其他类通用。麻将中,又分各个地区的,如:广东麻将,四川麻将,济南麻将等。这里就以这三个麻将为例,进行创建者模式讲解麻将流程的创建。
3.1 分析
1. 无论什么麻将,他们的流程是有差异的。比如:
a) 广东麻将流程:定庄->发牌->牌局摸打->牌局结束->结算
b) 四川麻将流程:定庄->发牌->定缺->换三张->牌局摸打->牌局结束->查花猪大叫->结算
c) 济南麻将流程: 定庄->发牌->飘->明楼->牌局摸打->牌局结束->结算
2. 整个牌局过程是有一定的流程的,为了自动化构建或个牌局流程,采用建创者模式构造好流程,然后程序按流程跟逻辑即可实现一个可配置,可通用的麻将流程
3.2具体实现方法
0. 麻将流程名定义
enum EMahjongProcedure
{
EMahjongProcedure_DingZhang = 1,// 定庄
EMahjongProcedure_FaPai ,// 发牌
EMahjongProcedure_DingQue,//定缺
EMahjongProcedure_HuanSanZhang,//换三张
EMahjongProcedure_Piao,//飘
EMahjongProcedure_MingLou,//明楼
EMahjongProcedure_Game,牌局摸打
EMahjongProcedure_GameOver,//牌局结束
EMahjongProcedure_JieSuan,//牌局结算
EMahjongProcedure_HuaZhu,//花猪
EMahjongProcedure_DaJiao,//大叫
}
1. 首先,有个麻将游戏流程的产品,棋类,牌类通用,名为:GameProcedure
class GameProcedure
{
public:
void addProcedure(EMahjongProcedure eProcedure)
{
int nowSize = _mapProcedureName.size();
_mapProcedure[nowSize+1] = eProcedure;
}
private:
std::map<int,int> _mapProcedure;
};
2. 有一个抽象建造者类,游戏抽象建创者,GameBuilder
class GameBuilder
{
public:
virtual ~GameBuilder(){}
virtual void builderDingZhang() = 0;// 定庄
virtual void builderFaPai() = 0;//发牌
virtual void builderDingQue() = 0;//定缺
virtual void builderHuanSanZhang() = 0;//换三张
virtual void builderPiao() = 0;//飘
virtual void builderMingLou() = 0;//明楼
virtual void builderGame() = 0;//牌局摸打
virtual void builderGameOver() = 0;//牌局结束
virtual void builderJieSuan() = 0;//牌局结算
virtual void builderHuaZhu() = 0;//花猪
virtual void builderDaJiao() = 0;//大叫
virtual GameProcedure* getGameProcedure() = 0;
//有新流程继续添加
};
3. 建造者实现类,MahjongGameBuilder
class MahjongGameBuilder: public GameBuilder
{
public:
MahjongGameBuilder()
{
_ptrGameProcedure = new GameProcedure();
}
void builderDingZhang()
{// 定庄
_ptrGameProcedure->addProcedure(EMahjongProcedure);
}
void builderFaPai()
{//发牌
_ptrGameProcedure->addProcedure(EMahjongProcedure_FaPai);
}
void builderDingQue()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_DingQue);
}
void builderHuanSanZhang()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_HuanSanZhang);
}
void builderPiao()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_Piao);
}
void builderMingLou()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_MingLou);
}
void builderGame()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_Game);
}
void builderGameOver()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_GameOver);
}
void builderJieSuan()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_JieSuan);
}
void builderHuaZhu()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_HuaZhu);
}
void builderDaJiao()
{
_ptrGameProcedure->addProcedure(EMahjongProcedure_DaJiao);
}
GameProcedure* getGameProcedure()
{
return _ptrGameProcedure;
}
private:
GameProcedure* _ptrGameProcedure;
};
4. 指挥者类,这里是麻将指挥者 MahjongDirector,棋类指挥者和牌类指挥者另建。
class MahjongDirector
{
public:
MahjongDirector(){}
MahjongDirector::~MahjongDirector(){}
//广东麻将流程
GameProduce* constructGuangDongMahjong(Builder* builder)
{
builder->builderDingZhang();
builder->builderFaPai();
builder->builderGame();
builder->builderGameOver();
builder->builderJieSuan();
return builder->getGameProcedure();
}
//四川麻将流程建造
GameProduce* constructSiChuangMahjong(Builder* builder)
{
builder->builderDingZhang();
builder->builderFaPai();
builder->builderDingQue();
builder->builderHuanSanZhang();
builder->builderGame();
builder->builderGameOver();
builder->builderHuaZhu();
builder->builderDaJiao();
builder->builderJieSuan();
return builder->getGameProcedure();
}
//济南麻将流程建造
GameProduce* constructJiNanMahjong(Builder* builder)
{
builder->builderDingZhang();
builder->builderFaPai();
builder->builderPiao();
builder->builderMingLou();
builder->builderGame();
builder->builderGameOver();
builder->builderHuaZhu();
return builder->getGameProcedure();
}
//新加大连麻将
GameProduce* constructDaLianMahjong(Builder* builder)
{
builder->builderDingZhang();
builder->builderFaPai();
builder->builderGame();
builder->builderGameOver();
return builder->getGameProcedure();
}
private:
Builder* _builder;
};
5. 麻将流程的生成
int main()
{
MahjongDirector* director = new MahjongDirector();
MahjongGameBuilder *gd_builder= new MahjongGameBuilder();
MahjongGameBuilder *sc_builder= new MahjongGameBuilder();
MahjongGameBuilder *jn_builder= new MahjongGameBuilder();
MahjongGameBuilder *dl_builder= new MahjongGameBuilder(); //新加大连麻将
GuangDongMahjong* gdMahjon = director.constructGuangDongMahjong(gd_builder);
GuangDongMahjong* scMahjon = director.constructSiChuangMahjong(sc_builder);
GuangDongMahjong* jnMahjon = director.constructJiNanMahjong(jn_builder);
GuangDongMahjong* dlMahjon = director.constructDaLianMahjong(jn_builder);//新加大连麻将
//释放指针
return 0;
}
6分析
a) 在这里创建了广东,四川,济南在个麻将流程,里面的具体流程细节是不一样的,用户创建麻将无须知道细节,只需创建相应地区即可。
b) 如果新加一个麻将,如果有新麻将,在Director中新加一个流程函数即可。新流程也要添加,但当流程非常完善时,新加麻将,只需加建造细节。constructXXXMahjong
可能有人会问:这里创建了麻将流程有什么用呢?
好处大着呢,如果全国有一万种不同的地方麻将,那么就有一万种麻将流程。流程大部份都是通用的,才写好了逻辑。如果新增一个新麻将,那么只需指挥者组装即可。
这里的流程,给程序按序列去执行,自动启关定时器,那么,就能实现一个通用的麻将游戏。即你想什么打法的麻将都可以,只需组装流程,就可以实现千千万万种的麻将,包括新创造的麻将流程玩法。够强大了吧。
4总结
今天想了一天,再想这个麻将流程的建造者实现方法,这里只是给出流程的拼装,非常通用,说明了建造者不用关心建造的具体细节,复杂的细节,就可以建造出各种各样复杂的产品。
一般来说,建造者用来复杂多变的产品上,同时又无须关心具体的实现细节。为使用者提供了一个简单的创建过程。同时具有良好的扩展性和复用性。是创建者模型中,应对复杂多变产品,为优选。
下一章节内容为原型模式,也就是对象的复制克隆。