设计模式应用之使用COMPOSITE模式实现流程(四)
2012-03-11 22:15
363 查看
设计模式应用之使用COMPOSITE模式实现流程(四)
最近在工作的过程中,完成了一个实现动态流程的任务。因此将我的demo程序共享出来,给大家参考如何使用COMPOSITE实现流程的编写。在前面序列文章,我本来计划利用MEMENTO
解耦COMPOSITE 对象,使COMPOSITE 对象得到共用,但是在实际开发过程中,我发现这样在开发上有一定的难度,因此我没有采用这样的思路去开发。
语音流程抽象起来包括:播放语音、播放菜单、还有其他叶子操作。因此语音流程的每个用户的每一选择,就构成了一棵状态子树。而这样的状态子树,如果采用常规的子树的遍历,这样的指针指向会指向很多层。因此我在实际开发过程中,抽象出一个TRootComposit 对象。具体的就不详细介绍了,我把不涉及到机密的东东,当作一个demo拿出来给大家参考。
以下是头文件:
最近在工作的过程中,完成了一个实现动态流程的任务。因此将我的demo程序共享出来,给大家参考如何使用COMPOSITE实现流程的编写。在前面序列文章,我本来计划利用MEMENTO
解耦COMPOSITE 对象,使COMPOSITE 对象得到共用,但是在实际开发过程中,我发现这样在开发上有一定的难度,因此我没有采用这样的思路去开发。
语音流程抽象起来包括:播放语音、播放菜单、还有其他叶子操作。因此语音流程的每个用户的每一选择,就构成了一棵状态子树。而这样的状态子树,如果采用常规的子树的遍历,这样的指针指向会指向很多层。因此我在实际开发过程中,抽象出一个TRootComposit 对象。具体的就不详细介绍了,我把不涉及到机密的东东,当作一个demo拿出来给大家参考。
以下是头文件:
#ifndef __COMPOMENT__H__ #define __COMPOMENT__H__ //------------------------------------------------------------------------------------------------------------- #include <string> #include <map> #include <vector> using namespace Unify; //------------------------------------------------------------------------------------------------------------- #define HANDLE_NEXT 1 //获取下一个节点(主要是composite对象) #define HANDLE_PRE 2 //获取上一个节点(主要是composite对象) #define HANDLE_END 3 //某一个流程分支都处理完 #define HANDLE_ERROR 4 //节点执行的操作有误 #define HANDLE_ERROR_NOTIFY 5 //节点执行错误,有提示 #define HANDLE_SELF 6 //驻留在节点执行 #define HANDLE_DEF 7 //默认的错误 //------------------------------------------------------------------------------------------------------------- class IvrCompoment { public: IvrCompoment(); virtual ~IvrCompoment(); //节点处理事件 virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e); //获取孩子节点 virtual IvrCompoment* getChild(const std::string& cond); //这个接口是判断是否是composit对象 virtual IvrCompoment* getComposite(); //用于返回上一级目录 virtual IvrCompoment* getPreCompoment(); //判断是否本compoment对象 virtual bool equal(const std::string& cond); //添加孩子节点,只要是composit对象 virtual void addChild(IvrCompoment* child); //递归构建树,可能要传入孩子信息 virtual void buildChild(DbServer::TRecordSetSeq& sRec); //设置本节点信息 virtual void set(DbServer::TRecordSet& rec); virtual void reset(); }; //------------------------------------------------------------------------------------------------------------- class IvrVoiceLeaf:public IvrCompoment { public: IvrVoiceLeaf(); ~IvrVoiceLeaf(); virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e); virtual bool equal(const std::string& cond); virtual void set(DbServer::TRecordSet& rec); private: std::string _actid; std::string _preid; std::string _condtion; std::string _actname; std::string _record; std::string _ttstext; std::string _recordfile; int _step; }; //------------------------------------------------------------------------------------------------------------- class IvrComposite:public IvrCompoment { public: IvrComposite(IvrCompoment* ivr); virtual ~IvrComposite(); virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e); //获取孩子节点 virtual IvrCompoment* getChild(const std::string& cond); //这个接口是判断是否是composit对象 virtual IvrCompoment* getComposite(); //用于返回上一级目录 virtual IvrCompoment* getPreCompoment(); //判断是否本compoment对象 virtual bool equal(const std::string& cond); //添加孩子节点,只要是composit对象 virtual void addChild(IvrCompoment* child); //递归构建树,可能要传入孩子信息 virtual void buildChild(DbServer::TRecordSetSeq& sRec); //设置本节点信息 virtual void set(DbServer::TRecordSet& rec); private: // 0 go to child,1 not bool CheckCond(const std::string& cond); std::string _actid; std::string _preid; std::string _condtion; std::string _actname; std::string _record; std::string _ttstext; std::string _recordfile; int _step; std::vector<IvrCompoment*> _childs; IvrCompoment* _preIvr; }; //------------------------------------------------------------------------------------------------------------- class TRootComposit:public IvrCompoment { public: TRootComposit(); ~TRootComposit(); virtual int handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e); virtual void buildChild(DbServer::TRecordSetSeq& sRec); virtual void reset(); //这个接口是判断是否是composit对象 virtual IvrCompoment* getComposite(){return this;} private: IvrCompoment* _root; IvrCompoment* _subRoot;//由于composit对象可能是一棵树 //_subRoot 指向下一个子树 }; //------------------------------------------------------------------------------------------------------------- class IvrMannage { public: ~IvrMannage(); int ReSetRoot(const std::string& key); int BuilderSessIvr(TIvrCallSessionInfo& s); int Handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e); int DeleteSessIvr(TIvrCallSessionInfo& s); static IvrMannage* instance(); private: IceUtil::RecMutex _mutex; IvrMannage(); static IvrMannage* _instance; std::map<std::string,IvrCompoment*> _ivrMap; }; //------------------------------------------------------------------------------------------------------------- #endif #include "Compoment.h" const int ErrorPlayLast = 90000; const int TopFlow = 1000; const int InToFlow = 2202; const int SelfFlow = 2101; const int QUITFlow = 94000; //--------------------------------------------------------------- //IvrMannage //--------------------------------------------------------------- IvrMannage* IvrMannage::_instance = NULL; IvrMannage* IvrMannage::instance() { if(_instance == NULL) { _instance = new IvrMannage(); } return _instance; } //--------------------------------------------------------------- IvrMannage::IvrMannage() { ; } //--------------------------------------------------------------- IvrMannage::~IvrMannage() { } //--------------------------------------------------------------- int IvrMannage::BuilderSessIvr(TIvrCallSessionInfo& s) { if(_ivrMap.find(s.SessionId) != _ivrMap.end()) return -1; DbServer::TRecordSetSeq selfInfo; int res = getAct(s,selfInfo);//获取某一个id的动态流程信心。 if(res <= 0) { return -1; } //find for root act unsigned int idx = 0; for(idx; idx < selfInfo.size();idx++) { disp_msg(2,"preid = [%s]",selfInfo[idx][2].c_str()); if(selfInfo[idx][2] == "-1") { break; } } if(idx >= selfInfo.size() || selfInfo.empty()) { disp_msg(2,"Enid =[%d] does not have Root Act",s.entid); return -1; } IvrCompoment* root; if(selfInfo.size() != 1) { root = new TRootComposit(); } else { root = new IvrVoiceLeaf(); } if(root == NULL) { disp_msg(2,"Enid =[%d] does new Act Error",s.entid); return -1; } root->buildChild(selfInfo); RecMutex::Lock lock(_mutex); _ivrMap.insert(std::make_pair(s.SessionId,root)); return 0; } //--------------------------------------------------------------- int IvrMannage::ReSetRoot(const std::string &key) { IceUtil::RecMutex::Lock lock(_mutex); std::map<std::string,IvrCompoment*>::iterator it; it = _ivrMap.find(key); if(it != _ivrMap.end()) { it->second->reset(); return 0; } return -1; } //--------------------------------------------------------------- int IvrMannage::DeleteSessIvr(TIvrCallSessionInfo& s) { RecMutex::Lock lock(_mutex); std::map<std::string,IvrCompoment*>::iterator it; it = _ivrMap.find(s.SessionId); if(it != _ivrMap.end()) { delete it->second; it->second = NULL; _ivrMap.erase(it); } return 0; } //--------------------------------------------------------------- //class IvrCompoment //--------------------------------------------------------------- IvrCompoment::IvrCompoment() { } //--------------------------------------------------------------- IvrCompoment::~IvrCompoment() { } //--------------------------------------------------------------- void IvrCompoment::addChild(IvrCompoment*) { } //--------------------------------------------------------------- int IvrCompoment::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e) { return 0; } //--------------------------------------------------------------- IvrCompoment* IvrCompoment::getChild(const std::string& cond) { return 0; } //--------------------------------------------------------------- IvrCompoment* IvrCompoment::getComposite() { return 0; } //--------------------------------------------------------------- IvrCompoment* IvrCompoment::getPreCompoment() { return 0; } //--------------------------------------------------------------- bool IvrCompoment::equal(const std::string& cond) { return true; } //--------------------------------------------------------------- void IvrCompoment::buildChild(DbServer::TRecordSetSeq& sRec) { } //--------------------------------------------------------------- void IvrCompoment::set(DbServer::TRecordSet& rec) { } //--------------------------------------------------------------- void IvrCompoment::reset() { } //--------------------------------------------------------------- //class IvrVoiceLeaf //--------------------------------------------------------------- IvrVoiceLeaf::IvrVoiceLeaf() { _step = 0; } //--------------------------------------------------------------- IvrVoiceLeaf::~IvrVoiceLeaf() { ; } //--------------------------------------------------------------- bool IvrVoiceLeaf::equal(const std::string& cond) { return (_condtion == cond); } //--------------------------------------------------------------- void IvrVoiceLeaf::set(DbServer::TRecordSet& rec) { /* os<<"select actid,acttype,preid," <<"condtion,actname,record,ttstext,recordfile from amrx_act" <<" where state = 0 and entid="<<sInfo.entid <<" order by preid"; */ _actid = rec[0]; _preid = rec[2]; _condtion = rec[3]; _actname = rec[4]; _record = rec[5]; _ttstext = rec[6]; _recordfile = rec[7]; } //--------------------------------------------------------------- int IvrVoiceLeaf::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e) { int v; bool b = false; while(!b) { disp_msg(3,"IvrVoiceLeaf:name = [%s],cond = [%s],step = [%d]", _actname.c_str(),_condtion.c_str(),_step); switch(_step) { case 0: if(_record == "1" && !_recordfile.empty()) { s.VoiceFile = _recordfile; setCallSession(s);//保存当前的信息 _step = 3; } else {//alloc tts allocTts(s.SessionId,1); b = true; _step = 1; } v = HANDLE_SELF; break; case 1: if(e.UCEventInfo.EventType == UCEventEndCall || e.UCEventInfo.ResCode != 0) { v = HANDLE_ERROR; } else {//tts change v = HANDLE_SELF; _step = 2; if(ttsChange(s.SessionId,_ttstext)) { v = HANDLE_ERROR; } } b = true; break; case 2: if(e.UCEventInfo.EventType == UCEventEndCall || e.UCEventInfo.ResCode != 0) { v = HANDLE_ERROR; b = true; } else { s.VoiceFile = e.UCEventInfo.TtsFileName; setCallSession(s); _step = 3; } break; case 3: v = HANDLE_SELF; b = true; _step = 4; if(playFileDtmf(s.SessionId,s.VoiceFile,1,0,5000)) { v = HANDLE_ERROR; } break; case 4: b = true; if(e.UCEventInfo.EventType == UCEventEndCall || e.UCEventInfo.ResCode != 0) { v = HANDLE_ERROR; } else { setSessionErrorCounts(s.SessionId,0); s.smstxt = _ttstext; setCallSession(s); v = HANDLE_END; } break; default: b = true; break; v = HANDLE_ERROR; } } if(v != HANDLE_SELF) _step = 0; return v; } //--------------------------------------------------------------- //IvrComposite //--------------------------------------------------------------- IvrComposite::IvrComposite(IvrCompoment* ivr): _preIvr(ivr), _step(0) { } //--------------------------------------------------------------- IvrComposite::~IvrComposite() { for(unsigned int i = 0; i < _childs.size();i++) delete _childs[i]; } //--------------------------------------------------------------- IvrCompoment* IvrComposite::getChild(const std::string& cond) { IvrCompoment* ivr = 0; for(unsigned int i = 0; i < _childs.size();i++) { if(_childs[i] !=0 && _childs[i]->equal(cond)) { ivr = _childs[i]; break; } } return ivr; } //--------------------------------------------------------------- IvrCompoment* IvrComposite::getComposite() { return this; } //--------------------------------------------------------------- IvrCompoment* IvrComposite::getPreCompoment() { return _preIvr; } //--------------------------------------------------------------- bool IvrComposite::equal(const std::string& cond) { return (_condtion == cond); } //--------------------------------------------------------------- void IvrComposite::addChild(IvrCompoment* child) { if(child != 0) _childs.push_back(child); } //--------------------------------------------------------------- void IvrComposite::set(DbServer::TRecordSet& rec) { _actid = rec[0]; _preid = rec[2]; _condtion = rec[3]; _actname = rec[4]; _record = rec[5]; _ttstext = rec[6]; _recordfile = rec[7]; } //--------------------------------------------------------------- void IvrComposite::buildChild(DbServer::TRecordSetSeq& sRec) {//递归构建该节点的子树 IvrCompoment* ivr; for(unsigned int i = 0; i < sRec.size();i++) { unsigned int j = 0; if(_actid == sRec[i][2]) {//找到该节点的子节点 for(j = 0; j < sRec.size();j++) {//判断是否是复合动作 if(sRec[i][0] == sRec[j][2]) break; } if(j < sRec.size()) {//是composite对象 ivr = new IvrComposite(this); } else {//Leaf object ivr = new IvrVoiceLeaf(); } if(ivr != 0) { ivr->set(sRec[i]); ivr->buildChild(sRec); addChild(ivr); } }//end if }//end for } //--------------------------------------------------------------- bool IvrComposite::CheckCond(const std::string& cond) { bool b = false; for(unsigned int i = 0; i < _childs.size(); i++) { if(_childs[i] != 0 && _childs[i]->equal(cond)) { b = true; break; } } return b; } //--------------------------------------------------------------- int IvrComposite::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e) { int v; bool b = false; std::string file; while(!b) { disp_msg(3,"IvrComposite:name = [%s],cond = [%s],step = [%d]", _actname.c_str(),_condtion.c_str(),_step); switch(_step) {//0 tts 1 file case 0: if(_record == "1" && !_recordfile.empty()) { s.VoiceFile = _recordfile; file = s.VoiceFile; gReSourcePool->setCallSession(s); _step = 3; } else {//alloc tts allocTts(s.SessionId,1); b = true; _step = 1; } v = HANDLE_SELF; break; case 1: if(e.UCEventInfo.EventType == UCEventEndCall || e.UCEventInfo.ResCode != 0) { v = HANDLE_ERROR; } else {//tts change v = HANDLE_SELF; _step = 2; if(ttsChange(s.SessionId,_ttstext)) { v = HANDLE_ERROR; } } b = true; break; case 2: if(e.UCEventInfo.EventType == UCEventEndCall || e.UCEventInfo.ResCode != 0) { v = HANDLE_ERROR; b = true; } else { s.VoiceFile = e.UCEventInfo.TtsFileName; file = s.VoiceFile; gReSourcePool->setCallSession(s); _step = 3; } break; case 3: v = HANDLE_SELF; b = true; if(playFileDtmf(s.SessionId,file,1,0,5000)) { v = HANDLE_ERROR; } _step = 4; break; case 4: if(e.UCEventInfo.EventType == UCEventEndCall || e.UCEventInfo.ResCode != 0) { v = HANDLE_ERROR; b = true; } else { if(e.UCEventInfo.Dtmf[0] =='*') { v = HANDLE_PRE; b = true; } else { if(CheckCond(e.UCEventInfo.Dtmf)) { v = HANDLE_NEXT; b = true; setSessionErrorCounts(s.SessionId,0); } else {//出错 if(addSessionErrorCounts(s.SessionId)<= gMaxErrCounts) { file = "amrx//errin;"+s.VoiceFile; _step = 3; } else { b = true; v = HANDLE_ERROR_NOTIFY; s.VoiceFile = "amrx//maxerr"; setCallSession(s); } } } } break; default: _step = 5; b = true; v = HANDLE_ERROR; break; }//end switch } if(v != HANDLE_SELF) _step = 0; return v; } //--------------------------------------------------------------- //TRootComposit //--------------------------------------------------------------- TRootComposit::TRootComposit(): _root(0), _subRoot(0) { } //--------------------------------------------------------------- TRootComposit::~TRootComposit() { delete _root; } //--------------------------------------------------------------- void TRootComposit::reset() { _subRoot = _root; } //--------------------------------------------------------------- void TRootComposit::buildChild(DbServer::TRecordSetSeq& sRec) { unsigned int idx = 0; for(idx; idx < sRec.size();idx++) { disp_msg(2,"preid = [%s]",sRec[idx][2].c_str()); if(sRec[idx][2] == "-1") { break; } } if(idx >= sRec.size()) { disp_msg(2,"TRootComposit build child Error = [no root act]"); return; } _root = new IvrComposite(0); if(_root != 0) { _root->set(sRec[idx]); _root->buildChild(sRec); _subRoot = _root; } } //--------------------------------------------------------------- int TRootComposit::handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e) { /* #define HANDLE_NEXT 1 //获取下一个节点(主要是composite对象) #define HANDLE_PRE 2 //获取上一个节点(主要是composite对象) #define HANDLE_END 3 //某一个流程分支都处理完 #define HANDLE_ERROR 4 //节点执行的操作有误 #define HANDLE_ERROR_NOTIFY 5 //节点执行错误,有提示 #define HANDLE_SELF 6 //驻留在节点执行 */ int v = HANDLE_ERROR; bool top = false; while(true) { v = HANDLE_DEF; if(_subRoot != 0) v = _subRoot->handle(s,e); switch(v) { case HANDLE_NEXT: _subRoot = _subRoot->getChild(e.UCEventInfo.Dtmf); break; case HANDLE_PRE: top = (_subRoot == _root); _subRoot = _subRoot->getPreCompoment(); if( top && _subRoot == 0) { _subRoot = _root; return TopFlow; } break; case HANDLE_END: //该流程的某个子树已经处理完了,返回到汇聚点 disp_msg(3,"TRootComposit 3 InToFlow=[%d]",InToFlow); return InToFlow; case HANDLE_ERROR: disp_msg(3,"TRootComposit 4 QUITFlow=[%d]",QUITFlow); return QUITFlow; case HANDLE_ERROR_NOTIFY: disp_msg(3,"TRootComposit 5 ErrorPlayLast=[%d]",ErrorPlayLast); return ErrorPlayLast; case HANDLE_SELF: disp_msg(3,"TRootComposit 6 SelfFlow=[%d]",SelfFlow); return SelfFlow; default: disp_msg(3,"TRootComposit 7 QUITFlow=[%d]",QUITFlow); return QUITFlow; }//end switch } } //--------------------------------------------------------------- int IvrMannage::Handle(TIvrCallSessionInfo& s,const TIvrAppEventInfo& e) { std::map<std::string,IvrCompoment*>::iterator it; IvrCompoment* root = 0; { IceUtil::RecMutex::Lock lock(_mutex); it = _ivrMap.find(s.SessionId); if(it != _ivrMap.end()) root = it->second; if(root == 0) return QUITFlow; } int v = QUITFlow; if(root->getComposite() == 0) { int v = root->handle(s,e); switch(v) { case HANDLE_END: v = InToFlow; break; case HANDLE_SELF: v = SelfFlow; break; default: v = QUITFlow; break; }//end if disp_msg(3,"IvrMannage::Handle Leaf return v =[%d]",v); return v; } else { v = root->handle(s,e); disp_msg(3,"IvrMannage::Handle RootComposit return v =[%d]",v); return v; } } //---------------------------------------------------------------
相关文章推荐
- 设计模式应用之使用COMPOSITE模式实现流程(三)
- 设计模式应用之使用COMPOSITE模式实现流程(一)
- 设计模式应用之使用COMPOSITE模式实现流程(二)
- Python设计模式中单例模式的实现及在Tornado中的应用
- 详解iOS应用开发中使用设计模式中的抽象工厂模式
- 解析iOS应用开发中对设计模式中的抽象工厂模式的实现
- 【设计模式】使用unity实现代理模式(Proxy mode)
- 使用 C# (.NET Core) 实现命令设计模式 (Command Pattern)
- 从今天开始学习iOS开发(iOS 7版)--实现一款App之使用设计模式
- 工作流模式详解之基本流程控制模式的应用与设计(1、2、3、4、5)
- 任何国家都无法限制数字货币。为什么呢? 要想明白这个问题需要具备一点区块链的基础知识: 区块链使用的大致技术包括以下几种: a.点对点网络设计 b.加密技术应用 c.分布式算法的实现 d.数据存储技术 e.拜占庭算法 f.权益证明POW,POS,DPOS 原因一: 点对点网络设计 其中点对点的P2P网络是bittorent ,由于是点对点的网络,没有中心化,因此在全球分布式的网
- 设计模式- 使用抽象工厂实现多数据库切换实现过程
- 设计模式-代理模式与适配器模式实现代码重用以及策略模式的使用
- 使用设计模式中的单例模式来实现C++的boost库
- 使用C++实现设计模式(连载): 第二回 Factory 工厂模式
- protocol的基本使用与代理设计模式的应用
- 在XHTML浏览器的设计中应用composite和visitor模式
- 使用 C#/.NET Core 实现单体设计模式
- PHP设计模式笔记:使用PHP实现单例模式
- 使用单例和工厂设计模式实现dao实现层的解耦