模块间互相调用的一种方法

模块间互相调用的一种方法

在程序设计中,需要把程序根据功能划分多个模块,多个模块间免不了互相调用一些服务函数,这样会使模块间剪不断,理还乱!

利用服务中心的思想,可以使各个模块间的关系比较简单。模块间的调用通过中心服务器交换,彼此没有联系,这样模块间可以到达低耦合,高内聚。

实现方法:

中心服务器:

 

class BASEFRAME_CLASS CIVMDlgSrvMgr 

{

         typedef map<string,CIVMBaseSrv*> SRVMAP;

         typedef map<string,CIVMBaseSrv*>::iterator SRVMAPPtr;

        

         typedef map<CIVMBaseSrv*,CIVMBaseSrv*> DLGMAP;

         typedef map<CIVMBaseSrv*,CIVMBaseSrv*>::iterator DLGMAPPtr;

        

public:

         CIVMDlgSrvMgr();

         virtual ~CIVMDlgSrvMgr();

 

public:

         static CIVMDlgSrvMgr* Instance();

         // 注册一个服务

         bool RegService( string strSrvName, CIVMBaseSrv* pProvider );

         // 注销一个服务

         void UnRegService( string strSrvName );

         // 注销一个服务提供者

         void UnRegProvider( CIVMBaseSrv* pProvider );

         // 请求一个服务

         bool QueryService( IN CIVMMsg& msg, OUT CIVMMsg& result );

         // 注册一个窗口

         void RegDlg( CIVMBaseSrv* pDlg );

         // 注销一个窗口

         void UnRegDlg( CIVMBaseSrv* pDlg );

         //

         void CloseNoneVideoWnd();

         //

         void DiableAllWnd();

         //

         void EnableAllWnd();

         //

         CIVMBaseSrv* GetRegDlg( string strDlgClassName );

 

protected:

         SRVMAP m_srvMap;

         DLGMAP m_dlgMap;

 

};

在程序中,定一个中心服务器单体:

CIVMDlgSrvMgr* g_pSrvMgr = NULL;

 

CIVMDlgSrvMgr* g_pSrvMgr = NULL;

//

// Construction/Destruction

//

 

CIVMDlgSrvMgr::CIVMDlgSrvMgr()

{

 

}

 

CIVMDlgSrvMgr::~CIVMDlgSrvMgr()

{

 

}

 

CIVMDlgSrvMgr* CIVMDlgSrvMgr::Instance()

{

         if ( g_pSrvMgr == NULL )

         {

                   g_pSrvMgr = new CIVMDlgSrvMgr();

                   ASSERT( g_pSrvMgr );

         }

 

         return g_pSrvMgr;

}

 

// 注册一个服务

bool CIVMDlgSrvMgr::RegService( string strSrvName, CIVMBaseSrv* pProvider )

{

         m_srvMap[strSrvName] = pProvider;

         return true;

}

 

// 注销一个服务

void CIVMDlgSrvMgr::UnRegService( string strSrvName )

{

         m_srvMap.erase(strSrvName);

}

        

// 注销一个服务提供者

void CIVMDlgSrvMgr::UnRegProvider( CIVMBaseSrv* pProvider )

{

         SRVMAPPtr itSrv = m_srvMap.begin();

         for ( ; itSrv != m_srvMap.end(); itSrv++ )

         {

                   if ( itSrv->second == pProvider )

                   {

                            itSrv = m_srvMap.erase( itSrv );

                   }

         }

}

 

// 请求一个服务

//用户需要调用另外一个模块的服务函数时,调用该函数。前提是:另外一个模块提供了这个服务函数,并向中心服务器注册了该函数,如何注册,下面会做介绍。

bool CIVMDlgSrvMgr::QueryService(IN CIVMMsg& msg, OUT CIVMMsg& result)

{

         string strQuerySrvName = msg.GetMsgName();

         CIVMBaseSrv* pSrvProvider = m_srvMap[strQuerySrvName];

         if ( pSrvProvider == NULL )

         {

                   return false;

         }

 

         return pSrvProvider->OnQueryMsg( msg, result );

}

 

// 注册一个窗口

void CIVMDlgSrvMgr::RegDlg( CIVMBaseSrv* pDlg )

{

         m_dlgMap[pDlg] = pDlg;

}

 

// 注销一个窗口

void CIVMDlgSrvMgr::UnRegDlg( CIVMBaseSrv* pDlg )

{

         DLGMAPPtr itDlg = m_dlgMap.begin();

         for ( ; itDlg != m_dlgMap.end(); itDlg++ )

         {

                   if ( itDlg->second == pDlg )

                   {

                            m_dlgMap.erase( itDlg );

                           

                            break;

                   }

         }

}

 

CIVMBaseSrv* CIVMDlgSrvMgr::GetRegDlg( string strDlgClassName )

{

         CIVMBaseDlg* pDlg = NULL;

         DLGMAPPtr itDlg = m_dlgMap.begin();

         for ( ; itDlg != m_dlgMap.end(); itDlg++ )

         {

                   pDlg = (CIVMBaseDlg*)(itDlg->second);

                   if ( pDlg && pDlg->m_strDlgName == strDlgClassName )

                   {

                            return pDlg;

                   }

         }

 

         return NULL;

}

 

void CIVMDlgSrvMgr::DiableAllWnd()

{

         CIVMBaseDlg* pWnd= NULL;

         DLGMAPPtr itDlg = m_dlgMap.begin();

         for ( ; itDlg != m_dlgMap.end(); itDlg++ )

         {

                   pWnd = (CIVMBaseDlg*)itDlg->second;

                   if ( pWnd && IsWindow(pWnd->m_hWnd) )

                   {

                            pWnd->EnableWindow(FALSE);

                   }

         }

}

 

void CIVMDlgSrvMgr::EnableAllWnd()

{

         CIVMBaseDlg* pWnd= NULL;

         DLGMAPPtr itDlg = m_dlgMap.begin();

         for ( ; itDlg != m_dlgMap.end(); itDlg++ )

         {

                   pWnd = (CIVMBaseDlg*)itDlg->second;

                   if ( pWnd && IsWindow(pWnd->m_hWnd) )

                   {

                            pWnd->EnableWindow(TRUE);

                   }

         }

}

 

//

void CIVMDlgSrvMgr::CloseNoneVideoWnd()

{

         CIVMBaseDlg* pWnd= NULL;

         DLGMAPPtr itDlg = m_dlgMap.begin();

         for ( ; itDlg != m_dlgMap.end(); itDlg++ )

         {

                   pWnd = (CIVMBaseDlg*)itDlg->second;

                   if ( pWnd && IsWindow(pWnd->m_hWnd) && pWnd->m_strDlgName != "CIVMMonitorDlg")

                   {

                            pWnd->SendMessage(WM_CLOSE);

                   }

         }

}

 

模块基类:

         模块需要继承一个统一接口,向中心服务器注册自己提供的服务函数,和调用中心服务器提供的接口来调用其他模块的函数。

基类定义:

//

// 服务类接口

class BASEFRAME_CLASS CIVMBaseSrv

{

public:

         CIVMBaseSrv(){};

         ~CIVMBaseSrv(){};

 

         // 服务响应函数

         virtual bool OnQueryMsg( CIVMMsg& msg, CIVMMsg& result );

 

         // 获取提供的服务名列表

         virtual bool GetSrvList( list<string>& srvList ){ return false; }

 

protected:

         // 注册自己的服务

         virtual bool RegistThisSrv()

         {

                   bool bRet = true;

                   list<string> srvList;

                   if ( GetSrvList(srvList) )

                   {

                            list<string>::iterator itSrv = srvList.begin();

                            for ( ; itSrv != srvList.end(); itSrv++ )

                            {

                                     bRet &= CIVMDlgSrvMgr::Instance()->RegService( *itSrv, this );

                            }

                   }

                  

                   return bRet;

         }

 

         // 注销自己的服务

         virtual void UnRegistThisSrv()

         {

                   CIVMDlgSrvMgr::Instance()->UnRegProvider( this );

         }

};

 

模块使用中心服务器互相调用的方法:

1.       模块要继承基类CIVMBaseSrv

2.       在启动模块时,调用     

// 注册窗口提供的服务

RegistThisSrv();

并实现:

// 获取提供的服务名列表

bool CIVMEQMainDlg::GetSrvList( list<string>& srvList )

{

if ( m_bHasRecSrv == false )

{

           return false;

}

srvList.push_back( SRV_EQ_STATUS );

srvList.push_back( SRV_EQ_FRESH );

srvList.push_back( SRV_EQ_CLEAR );

#ifdef _DIANLI_SMS_

srvList.push_back( SRV_SMTK_CONTROL_CYCLE );

#endif

 

return true;

}

来注入自己提供的服务名称。

3.       实现自己提供的服务函数

4.       // 服务响应函数

bool CIVMEQMainDlg::OnQueryMsg( CIVMMsg& msg, CIVMMsg& result )

{

         IVMFUNCTRACE("CIVMEQMainDlg::OnQueryMsg");

 

         int nRecID = 0;

         string strMsgName = msg.GetMsgName();

         CIVMMsgBody* pBody = msg.GetBody();

         string strTmp = msg.ToString();

        

         if ( strMsgName == SRV_EQ_STATUS )

         {

                   char* pszPUID = pBody->GetTag( "PUID", true );

                   char* pszChnNo = pBody->GetTag( "ChnNo", true );

                   CIVMEQTree::ENDoOnVChn nArm =

                            pBody->GetTagInt( "Arm", true ) == 1 ? CIVMEQTree::DOV_ARMSTART : CIVMEQTree::DOV_ARMSTOP;

 

                   if ( pszPUID && pszChnNo )

                   {

                            CIVMDataItemVChn* pChn = m_eqtree.m_pEQData->GetChn( pszPUID, pszChnNo );

            if (pChn != NULL)

            {

                if ( nArm == CIVMEQTree::DOV_ARMSTART )

                {

                    pChn->Arm( 0 );

                }

                else

                {

                    pChn->DisArm();

                                }

            }

                   }

         }

         else if ( strMsgName == SRV_EQ_FRESH )

         {

                   (void)m_eqtree.FreshTreeData();

         }

         else if ( strMsgName == SRV_EQ_CLEAR )

         {

                   StopTimer();

 

                   StopAllVideo();

                  

                   LOCK_DATA(m_eqtree.m_pEQData);

                   StopAllVideo();

                   m_eqtree.m_pEQData->Clear();

                   UNLOCK_DATA(m_eqtree.m_pEQData);

                  

                   (void)m_eqtree.FreshTreeData();

 

                   StartTimer();

         }

#ifdef _DIANLI_SMS_

         else if ( strMsgName == SRV_SMTK_CONTROL_CYCLE )

         {

                   CIVMMsgNode* pNode = msg.GetSingleNode("ControlSMTK");

                   ASSERT( pNode );

                  

                   if ( pNode )

                   {

                            char* pszAction = pNode->GetTag(TAG_ACTION);

                            if ( NULL == pszAction )

                                     return false;

                            int   nAction = atoi(pszAction);

                            string strEQID = "";

                            CIVMDataItemEQ* pEQ = NULL;

                            strEQID = pNode->GetTag("PUID");

                            if (!strEQID.empty())

                            {

                                     pEQ = m_eqtree.m_pEQData->GetDataItem(strEQID);

                                     if ( NULL == pEQ )

                                               return false;

                            }

                            //判断action的值来决定是启动SMTK还是关闭SMTK

                            if ( nAction == 1 )//唤醒电源系统

                            {

                                     //m_eqtree.OpenMainCtrlMoudle(pEQ);

                                     m_eqtree.SMSOperate(pEQ, 2);

                            }

                            else if ( nAction == 0) //休眠电源系统

                            {

                                     //m_eqtree.CloseMainCtrlMoudle(pEQ);

                                     //

                                     m_eqtree.SMSOperate(pEQ, 3);

                            }

                   }

         }

#endif

         else

         {

                   ASSERT( 0 );

         }

        

         return nRecID > 0 ? true : false;

}

 

 

这样其他模块就可以根据服务名字来调用该模块的服务函数。注意:

1.       服务函数不能阻塞,否则会引起调用者的阻塞。

2.       CIVMMsg只是一个XML结构体,用户可以自己实现。

3.       调用服务函数的结果放在, CIVMMsg& result中。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模块支持GBK、UNICODE、UTF-8三种编码之互相转换,不依赖系统Api,通过查表和编码算法直接得出转码结果,支持多线程调用。 编码小科普 GBK编码:1-2个字节,包含GB2312、ASCII、BIG5,注意:同一个繁体字在GBK和BIG5中的编码是各不相同的。 GB18030编码:1字节、2字节、4字节,兼容GBK。 UNICODE是国际统一编码,UCS-2标准:2字节,UCS-4标准:4字节。 UTF-8是对UNICODE的再次编码,UCS-2标准:1-3字节,UCS-4标准:1-6字节。 BIG5编码:2字节,繁体中文,主要在台湾、香港、澳门等地普及,属于业界标准而非官方标准。 比用Api“MultiByteToWideChar、WideCharToMultiByte”的有两个好处 。1,Api的可能造成程序崩溃(相信很多人都遇到过),使用过多个易语言界大佬的编码转换都会出现这个情况,而我这个模块就不会。2,Api的如果大家使用代码页936进行转换,很多GBK字符不受支持,因为代码页936表示的是简体中文(MSDN解释:GB2312,ANSI / OEM简体中文(中国,新加坡);简体中文(GB2312)),GB2312只有几千个字符,相比GBK少了一万多个字符。 所以你不必担心转换的字符会少,我可以负责任的说只会比你用上面两个api支持的字符多,不会少。至于转换速度也并不会慢,我的查表是直接定位位置,没有查找过程,速度不会慢。下一次更新准备添加支持BIG5编码转换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值