现在就来看看数据库发包模式
这个用到了抽象工厂模式
其实经理的那个差不多都是注册具体工厂到抽象工厂,只是这里不是抽象工厂而是PktFactoryMgr功能和抽象工厂差不多
{
#define __REGISTER_DB_PKT_CREATEFUNCTION(DBOptClassType)
Register<DBOptClassType>(PktSingleFactory<DBOptClassType>::GetOrCreateInstance());
__REGISTER_DB_PKT_CREATEFUNCTION(AskActorList);//注册包工厂到m_vecPktConstructor中
__REGISTER_DB_PKT_CREATEFUNCTION(AskActorInfo);
__REGISTER_DB_PKT_CREATEFUNCTION(AskActorInfoEx);
__REGISTER_DB_PKT_CREATEFUNCTION(AskUserInfo);
}
m_vecPktConstructor[pFactory->GetPktID()] =
new FnPktCreate(std::bind(&PktSingleFactory<T>::CreatePkt, pFactory));
我任务PktSingleFactory就相当于具体工厂,将具体工厂类注册金抽象工厂类
void asynDBCenter::GetUserInfo(std::function<void(bool bExist, const ShuiHu::UserInfo& hr)>* fnGetUserInfo, const char* pszName)
{
//抽象工厂根据注册进去的具体工厂创建具体产品,但有点疑问就是抽象工厂具体工厂可以创建多个具体产品类的实例,但CreatePkt是显示的去new
DB::AskUserInfo* pAskPkt = dynamic_cast<DB::AskUserInfo*>(m_pPktFacMgr->CreatePkt(DB::eDBOpt_AskUserInfo));
//InterruptStream流内部封装操作,没什么
DB::InterruptStream SendStream(m_pSendBuffer, eMaxSendBufferSize);
DB::DBOptID eOptID = pAskPkt->GetID();
SendStream.CopyIn(&eOptID, sizeof(DB::DBOptID)); // 操作ID
pAskPkt->m_uFlag = (unsigned __int64)fnGetUserInfo; // 识别标记
strncpy(pAskPkt->m_aUserName, pszName, MAX_NAME_LEN);
pAskPkt->Write(SendStream);
//DestroyPkt又显示的delete,每次发包去new,delete容易造成内存碎片
m_pPktFacMgr->DestroyPkt(pAskPkt);
PushShmInter(SendStream);
}
DBSvr那边根据接收的数据创建介入式流,从其中读取ID创建相应的包,然后从包从介入式流中读取数据,在根据包的ID解析数据访问数据库