您的位置:首页 > 其它

再谈谈注冊(本质是建立映射)与回调

2016-02-29 09:31 411 查看
在之前的博文中, 我们探讨过映射的重要作用。 请直接看:http://blog.csdn.net/stpeace/article/details/39452203, 在那篇文章中, 我们是用STL中的map来做的, map建立的是key-value映射, 在本文中, 我们自己来建立映射, 并讨论一个更为复杂的程序, 顺便再次复习一下注冊与回调。

注冊与回调? 有那么复杂么?没有必要过多地扯了, 直接上代码:

#include <iostream>
#include <vector>
using namespace std;

// 前向声明
class BasicMod;

//类函数指针类型
typedef void (BasicMod:: *PFun)(const char* pParaName);

// 映射结点
typedef struct
{
BasicMod *pMod;
char szParaName[1024];
PFun operTypeOne;
PFun operTypeTwo;
PFun operTypeThree;
}MyMap;

// 用全局的g_pv保存结点指针
vector<MyMap *> g_pv;

// 运行类, 提供注冊, 查找接口, 并运行回调操作
class Do
{
public:
// 单例
static Do *getInstance()
{
static Do *p = NULL;
if(NULL == p)
{
p = new Do;
}

return p;
}

// 注冊接口
void regNode(BasicMod *pb, MyMap *pmap, int i)
{
MyMap *p = new MyMap;
p->pMod = pb;
memset(p->szParaName, 0, sizeof(p->szParaName));
strncpy(p->szParaName, (pmap + i)->szParaName, sizeof(p->szParaName) - 1);
p->operTypeOne = (pmap + i)->operTypeOne;
p->operTypeTwo = (pmap + i)->operTypeTwo;
p->operTypeThree = (pmap + i)->operTypeThree;

g_pv.push_back(p);
}

// 查找接口
MyMap *findNode(const char *pParaName)
{
int n = g_pv.size();
int i = 0;
for(i = 0; i < n; i++)
{
if(0 == strcmp(g_pv[i]->szParaName, pParaName))
{
return g_pv[i];
}
}

return NULL;
}

// 运行回调操作
void exect(const char *pParaName)
{
MyMap *p = findNode(pParaName);
if(NULL != p && NULL != p->pMod)
{
((p->pMod)->*(p->operTypeOne))(pParaName);
((p->pMod)->*(p->operTypeTwo))(pParaName);
((p->pMod)->*(p->operTypeThree))(pParaName);
}
}
};

// 基类
class BasicMod
{
public:
void reg(BasicMod *pm, MyMap *p, int i)
{
Do::getInstance()->regNode(pm, p, i);
}
};

// 格式化
#define TOGETHER(mod, name, f1, f2, f3) {NULL, name, (PFun)(&mod::f1), (PFun)(&mod::f2), (PFun)(&mod::f3)}

// 模块1
class Mod1 : public BasicMod
{
public:
static Mod1* getInstance()
{
static Mod1* p = NULL;
if(NULL == p)
{
p = new Mod1;
}

return p;
}

// 模块1的初始化
void init()
{
MyMap mapArr[] =
{
TOGETHER(Mod1, "cpu", fun1Cpu, fun2Cpu, fun3Cpu),
};

int n = sizeof(mapArr) / sizeof(mapArr[0]);
int i = 0;
for(i = 0; i < n; i++)
{
// 注冊
reg(getInstance(), mapArr, i);
}
}

// 提供回调接口
void fun1Cpu(const char *pParaName)
{
cout << "mod1, pParaName is " << pParaName << endl;
}

// 提供回调接口
void fun2Cpu(const char *pParaName)
{
cout << "mod1, pParaName is " << pParaName << endl;
}

// 提供回调接口
void fun3Cpu(const char *pParaName)
{
cout << "mod1, pParaName is " << pParaName << endl;
}
};

class Mod2 : public BasicMod
{
public:
static Mod2* getInstance()
{
static Mod2* p = NULL;
if(NULL == p)
{
p = new Mod2;
}

return p;
}

void init()
{
MyMap mapArr[] =
{
TOGETHER(Mod2, "flash", fun1Flash, fun2Flash, fun3Flash),
};

int n = sizeof(mapArr) / sizeof(mapArr[0]);
int i = 0;
for(i = 0; i < n; i++)
{
reg(getInstance(), mapArr, i);
}
}

void fun1Flash(const char *pParaName)
{
cout << "mod2, pParaName is " << pParaName << endl;
}

void fun2Flash(const char *pParaName)
{
cout << "mod2, pParaName is " << pParaName << endl;
}

void fun3Flash(const char *pParaName)
{
cout << "mod2, pParaName is " << pParaName << endl;
}
};

int main()
{
// 模块初始化
Mod1::getInstance()->init();
Mod2::getInstance()->init();

// 运行操作
Do::getInstance()->exect("cpu");
Do::getInstance()->exect("flash");
Do::getInstance()->exect("mem");

return 0;
}


程序的结果为:

mod1, pParaName is cpu

mod1, pParaName is cpu

mod1, pParaName is cpu

mod2, pParaName is flash

mod2, pParaName is flash

mod2, pParaName is flash

我们也能够对上述程序作一下等价变换, 得到:

#include <iostream>
#include <vector>
using namespace std;

// 前向声明
class BasicMod;

//类函数指针类型
typedef void (BasicMod:: *PFun)(const char* pParaName);

// 映射结点
typedef struct
{
BasicMod *pMod;
char szParaName[1024];
PFun operTypeOne;
PFun operTypeTwo;
PFun operTypeThree;
}MyMap;

// 用全局的g_pv保存结点指针
vector<MyMap *> g_pv;

// 运行类, 提供注冊, 查找接口, 并运行回调操作
class Do
{
public:
// 单例
static Do *getInstance()
{
static Do *p = NULL;
if(NULL == p)
{
p = new Do;
}

return p;
}

// 注冊接口
void regNode(BasicMod *pm, const char *pParaName, PFun one, PFun two, PFun three)
{
MyMap *p = new MyMap;
p->pMod = pm;
memset(p->szParaName, 0, sizeof(p->szParaName));
strncpy(p->szParaName, pParaName, sizeof(p->szParaName) - 1);
p->operTypeOne = one;
p->operTypeTwo = two;
p->operTypeThree = three;

g_pv.push_back(p);
}

// 查找接口
MyMap *findNode(const char *pParaName)
{
int n = g_pv.size();
int i = 0;
for(i = 0; i < n; i++)
{
if(0 == strcmp(g_pv[i]->szParaName, pParaName))
{
return g_pv[i];
}
}

return NULL;
}

// 运行回调操作
void exect(const char *pParaName)
{
MyMap *p = findNode(pParaName);
if(NULL != p && NULL != p->pMod)
{
((p->pMod)->*(p->operTypeOne))(pParaName);
((p->pMod)->*(p->operTypeTwo))(pParaName);
((p->pMod)->*(p->operTypeThree))(pParaName);
}
}
};

// 基类
class BasicMod
{
public:
void reg(const char *pParaName, PFun one, PFun two, PFun three)
{
Do::getInstance()->regNode(this, pParaName, one, two, three);
}
};

// 格式化
#define TOGETHER(mod, name, f1, f2, f3) {NULL, name, (PFun)(&mod::f1), (PFun)(&mod::f2), (PFun)(&mod::f3)}

// 模块1
class Mod1 : public BasicMod
{
public:
static Mod1* getInstance()
{
static Mod1* p = NULL;
if(NULL == p)
{
p = new Mod1;
}

return p;
}

// 模块1的初始化
void init()
{
MyMap mapArr[] =
{
TOGETHER(Mod1, "cpu", fun1Cpu, fun2Cpu, fun3Cpu),
};

int n = sizeof(mapArr) / sizeof(mapArr[0]);
int i = 0;
for(i = 0; i < n; i++)
{
// 注冊
reg(mapArr[i].szParaName, mapArr[i].operTypeOne, mapArr[i].operTypeTwo, mapArr[i].operTypeThree);
}
}

// 提供回调接口
void fun1Cpu(const char *pParaName)
{
cout << "mod1, pParaName is " << pParaName << endl;
}

// 提供回调接口
void fun2Cpu(const char *pParaName)
{
cout << "mod1, pParaName is " << pParaName << endl;
}

// 提供回调接口
void fun3Cpu(const char *pParaName)
{
cout << "mod1, pParaName is " << pParaName << endl;
}
};

class Mod2 : public BasicMod
{
public:
static Mod2* getInstance()
{
static Mod2* p = NULL;
if(NULL == p)
{
p = new Mod2;
}

return p;
}

void init()
{
MyMap mapArr[] =
{
TOGETHER(Mod2, "flash", fun1Flash, fun2Flash, fun3Flash),
};

int n = sizeof(mapArr) / sizeof(mapArr[0]);
int i = 0;
for(i = 0; i < n; i++)
{
reg(mapArr[i].szParaName, mapArr[i].operTypeOne, mapArr[i].operTypeTwo, mapArr[i].operTypeThree);
}
}

void fun1Flash(const char *pParaName)
{
cout << "mod2, pParaName is " << pParaName << endl;
}

void fun2Flash(const char *pParaName)
{
cout << "mod2, pParaName is " << pParaName << endl;
}

void fun3Flash(const char *pParaName)
{
cout << "mod2, pParaName is " << pParaName << endl;
}
};

int main()
{
// 模块初始化
Mod1::getInstance()->init();
Mod2::getInstance()->init();

// 运行操作
Do::getInstance()->exect("cpu");
Do::getInstance()->exect("flash");
Do::getInstance()->exect("mem");

return 0;
}


我们看到, 上述程序建立了一个name对于{f1, f2, f3}的映射。 适用范围更广。

并且, 以后假设再加字段。 程序员仅仅须要注意三处就可以: 1. 添加initialize函数中数组中的项(添加映射);2. 在类中实现回调接口(添加回调接口); 3.在main中启动调用(启动运行)。

当然啦, 假设要添加模块3, 那也是非常easy的。

反思一下:

我突然发现。 我把上面的程序写复杂了。 事实上, 也能够用STL map建立name到f1, f2, f3的映射, 此时, 要把{f1, f2, f3}看成一个总体, 上述程序用STL map进行改造后,
会更好, 有兴趣的朋友能够试试。 我相信: 一次刻骨铭心的体验胜过千百次说教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: