使用小技巧使子功能模塊不污染主框架

  使用C++開發在作消息分發的時候咱們常常會遇到這樣的場景,咱們爲每一個消息設計了單獨的處理類或者處理函數,並用一個映射去維護這樣的對應關係,當消息來的時候,咱們遍歷這個映射表,找到對應的處理函數,進而處理消息。ios

  咱們可能遇到了這樣的設計函數

#include"case1.h"
#include"case2.h"
#include"case3.h"
#include"case4.h"
#include"case5.h"

void HandleManage::reghandle(){
     _mhandles["cmd_1"] = new case1_handle();
     _mhandles["cmd_2"] = new case2_handle();
     _mhandles["cmd_3"] = new case3_handle();
     _mhandles["cmd_4"] = new case4_handle();
     _mhandles["cmd_5"] = new case5_handle();
}

 這樣設計知足了咱們的要求,可是會帶來兩個問題測試

   一、隨着迭代開發的進行,會有大量新的case進來,這樣regHandle會變得很是長,並且同時會有大量的case已經再也不有用,佔用了映射表的同時也下降了消息映射的查找效率spa

   二、當咱們不想使用舊的case的時候,註冊模塊須要手動刪除,維護起來比較困難設計

爲了解決這兩個問題我打算從新設計handle管理模塊:code

HandleManage.hblog

#pragma once
#include <map>
#include <string>
#include "IHandle.h"
using namespace std;
class HandleManager
{
public:
    static HandleManager* instance() {
        if (_pInstance == NULL) {
            _pInstance = new HandleManager();
        }
        return _pInstance;
    }

    void regHandle(const string& cmd, IHandle* handle);
    void unregHandle(const string& cmd);
    IHandle * getHandle(const string& cmd);
    void onHandle(const string& cmd);
private:
    map<string, IHandle*> _map_handle;
    HandleManager(){}
    static HandleManager* _pInstance;
};

HandleManage.cpp接口

#include "HandleManager.h"

HandleManager* HandleManager::_pInstance = NULL;

void HandleManager::regHandle(const string& cmd, IHandle* handle) {
    _map_handle[cmd] = handle;
}

void HandleManager::unregHandle(const string& cmd) {
    if (_map_handle.find(cmd) != _map_handle.end()) {
        _map_handle.erase(cmd);
    }
}

IHandle * HandleManager::getHandle(const string& cmd) {
    if (_map_handle.find(cmd) != _map_handle.end()) {
        return _map_handle[cmd];
    }
    return NULL;
}

void HandleManager::onHandle(const string& cmd) {
    IHandle * pHandle = getHandle(cmd);
    if (NULL != pHandle) {
        pHandle->handle(cmd);
    }
}

IHandle.h 消息處理的統一接口進程

#pragma once
#include<string>
using namespace std;
class IHandle
{
public:
    virtual void handle(const string& cmd) = 0;
};

當咱們每開發一個case的時候爲期創建惟一的文件夾(f方便makefile添加編譯路徑)開發

以一個case爲例:

case_1.h

#pragma once
#include <string>
#include "../manager/HandleManager.h"
using namespace std;
const static string strCmd = "case_1";
class Case_1:public IHandle,public IConfig
{
public:
    static Case_1* instance() {
        if (_pInstance == NULL) {
            _pInstance = new Case_1();
        }

        if (_pInstance != NULL) {
            HandleManager::instance()->regHandle(strCmd, _pInstance);

        }
        return _pInstance;
    }
    void handle(const string& cmd);
private:
    static Case_1* _pInstance;
    Case_1(){}
};

static Case_1 * spInstance = Case_1::instance();

case_1.cpp

#include "Case_1.h"
#include <iostream>

Case_1* Case_1::_pInstance = NULL;

void Case_1::handle(const string& cmd) {
    cout <<"handle:"<< cmd << endl;
}

測試代碼以下:

#include "test/manager/HandleManager.h"
using namespace std;

int main(){

    HandleManager::instance()->onHandle("case_1");
    HandleManager::instance()->onHandle("case_2");

    system("pause");
}

  能夠看到在測試入口和handleManager都沒有關於具體case的任何代碼,而是在每一個case模塊將處理函數注入到消息映射表中,同時利用外部變量的特性,在運行最開始時就能被調用

       當有新的需求case合入或者舊的case過時的時候,咱們只需修改Makefile就能保證最後的進程只包含有效的case代碼

相關文章
相關標籤/搜索