设计模式的C语言实现--事件处理

设计模式的C语言实现--事件处理

嵌入式软件都是接受到一个事件,然后处理。简单的可以是一个按键点灯程序。检测到按键便是一个事件,点灯便是事件的处理。

用代码可以这样表达

static void LedOn() \\点亮一个LED

{

...

}

static int isKeyDown() \\检测按键是否按下

{

...

}

int main()

{

while(1){

if(isKeyDown()) //事件检测

LedOn(); //事件处理

}

}

可是如果我们要为刚刚的软件实现再添加一个温度过高预警功能呢?

static void LedOn() \\点亮一个LED

{

...

}

static int isKeyDown() \\检测按键是否按下

{

...

}

static void Alarm() \\预警

{

...

}

static int isTemperatureHigh()检测温度是否过高

{

...

}

int main()

{

while(1){

if(isKeyDown()) //事件检测

LedOn(); //事件处理

if(isTemperatureHigh()) //事件检测

Alarm(); //事件处理

}

}

我们看到,随着事件的增多,main函数里面的内容势必越来越多,代码的可读性越来越差。我们先给出一个解决方案。

typedef void (*eventHandler)(); //函数指针的声明

eventHandler findEventHandler(int event) //根据event编号,寻找eventHandler

{

...

}

int Event()

{

if(...)

return event //有事件产生,返回事件编号

return -1; //没有事件产生,返回-1

}

int main()

{

int event;

eventHandler func;

while(1){

event = Event(); //事件检测

if(event != -1){

func = findEventHandler(event); //事件匹配

func(); //事件处理

}

}

}

现在问题的难点,变成了怎么样实现event和eventHandler的绑定。

typedef void (*eventHandler)(); //函数指针的声明

static int EVENT = 0; //int为16bit

static int firstBitEqualOne(int event) //返回event中第一个等于1的bit位

{

...

}

static void setBit(int event,int pos) //将event的第pos位置1

{

....

}

void keyDownEvent() //在中断中实现

{

if(isKeyDown())

setBit(EVENT,KEYDONW); //设置事件

}

static void LedOn() \\点亮一个LED

{

...

}

#define KEYDOWN 3 //按键按下的事件为3

static eventHandler[16] = {NULL,NULL,NULL,LedOn,NULL ....};//LedOn的数组下标为3

eventHandler findEventHandler(int event) //根据event编号,寻找eventHandler

{

return eventHandler[event];

}

int Event()

{

if(EVENT != 0)

return firstBitEqualOne(EVENT) //有事件产生,返回事件编号

return -1; //没有事件产生,返回-1

}

int main()

{

int event;

eventHandler func;

while(1){

event = Event(); //事件检测,可以检测到按键按下

if(event != -1){

func = findEventHandler(event); //事件匹配,可以匹配到LedOn函数

func(); //事件处理,调用LedOn函数

}

}

}

这种匹配方案比较节省资源,写起来也比较简单。我们对比一下有无事件处理两种框架的实现方式

static void LedOn() \\点亮一个LED,有无事件处理框架,代码都一样

{

...

}

static int isKeyDown() \\检测按键是否按下,需要在中断中配合标志位

{

...

}

void keyDownEvent() //在中断中实现 ,事件某种程度上实现了标志位的功能。

{

if(isKeyDown())

setBit(EVENT,KEYDONW); //设置事件

}

//带有事件处理框架的程序,多了一步事件注册的代码,如下

#define KEYDOWN 3 //按键按下的事件为3

static eventHandler[16] = {NULL,NULL,NULL,LedOn,NULL ....};//LedOn的数组下标为3

//无事件处理框架

int main()

{

while(1){

if(isKeyDown()) //事件检测

LedOn(); //事件处理

if(...) //其他事件,每添加一个事件都需要修改main的执行流,容易产生错误

...

}

}

//事件处理框架,main函数不用改动

int main()

{

int event;

eventHandler func;

while(1){

event = Event(); //事件检测,可以检测到按键按下

if(event != -1){

func = findEventHandler(event); //事件匹配,可以匹配到LedOn函数

func(); //事件处理,调用LedOn函数

}

}

}

相关推荐

血色残阳套详细剖析
日博365哪个是真的

血色残阳套详细剖析

春兰空调通用遥控器
365bet哪个国家的

春兰空调通用遥控器

热血无赖dlc怎么用 热血无赖dlc安装教程
365bet哪个国家的

热血无赖dlc怎么用 热血无赖dlc安装教程

全民钱包 之前还有的时候 申请没通过 今天试了一下 8000 显示放款中 不知道稳不稳
日博365哪个是真的

全民钱包 之前还有的时候 申请没通过 今天试了一下 8000 显示放款中 不知道稳不稳

求车载充气泵使用方法,如何正确操作,步骤是什么
365彩票下载1.0.0老版本

求车载充气泵使用方法,如何正确操作,步骤是什么

苹果手机突然相机不能拍照了,修复它的7个方法
365bet哪个国家的

苹果手机突然相机不能拍照了,修复它的7个方法