zoukankan      html  css  js  c++  java
  • 再谈谈注冊(本质是建立映射)与回调

            在之前的博文中, 我们探讨过映射的重要作用。 请直接看: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进行改造后, 会更好, 有兴趣的朋友能够试试。 我相信: 一次刻骨铭心的体验胜过千百次说教。





  • 相关阅读:
    数据库反范式~认识三大范式
    王家林的“云计算分布式大数据Hadoop实战高手之路从零开始”的第五讲Hadoop图文训练课程:解决典型Hadoop分布式集群环境搭建问题
    linux网络编程之System V 信号量(三):基于生产者消费者模型实现先进先出的共享内存段
    html知识点总结
    [置顶] HTML5开源RPG游戏引擎lufylegendRPG 1.0.0发布
    通过Android trace文件分析死锁ANR
    黄金连分数 蓝桥杯
    vxworks 6.9.3.1
    poj 3468 A Simple Problem with Integers(线段树区区)
    关于Java序列化的一些高级用法
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5226384.html
Copyright © 2011-2022 走看看