`
xusaomaiss
  • 浏览: 615393 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

在嵌入式中结合设计模式的一个小应用【观察都模式】

阅读更多

序:

      最近在看一本关于设计模式的<<head first 设计模式>>,感觉不错,根据看到的一些东西,回头看看自己原来写的代码,做了一次:知行合一。此书看后,感觉对原来很多东西有所感悟,就差去家当和尚。此书可以反复研读,已经计划看完遍之后,再过一段时间再看。不过模式再好,也是需要拿使用的。

 

正文:  

      本人在mtk平台上做串口应用有一段时间了,从最初要实现的文件传输,到现在外接各种设备,串口应用已经多达四种。

      最初初现文件传输时,只是简单的在mtk层数据接收处理函数中添加文件传输处理的接口。

如下:

HandleMMIReceivedData(int port ,char *pData,int nDataLen)
{
    //处理文件传输
    Deal_FileTransmit(pData,nDataLen);
}

 因为最初只使用一个端口,只有一个功能模块。

之后,串口应用又添加了,打印,AT等,串口从原来一个变成现在的三个,之后的代码变成:

typedef enum 
{
		PHONE_WAIT=1,			/*待机状态*/
		PHONE_DATA_BACKUP=2,	/*数据备份状态 */
		PHONE_CALL=7,			/*通话状态*/
		//…………………其它状态
		PHONE_NULL
}PHONE_STATUS_E;

/************************************************************************/
/* 取得话机状态                                                         */
/************************************************************************/
int GetPhoneStatus_by_port(unsigned char m_port )
{
	return g_phoneStatus_byport[m_port];
}

/************************************************************************/
/* 设置话机状态                                                         */
/************************************************************************/
void SetPhoneStatus_by_port(int nStatus,unsigned char m_port  )
{
	g_phoneStatus_byport[m_port] = nStatus;
}

/************************************************************************/
/*串口数据处理                                         */
/************************************************************************/
HandleMMIReceivedData(int port,char *pData,int nDataLen)
{
       if ( port==g_print_uartPort &&nPhoneStatus ==PHONE_PRINT )//打印
	{		   
	   Print_Handle_RecvData(m_RBuf,buffLen);   
	}
        else if ( port==g_at_uartPort &&nPhoneStatus ==PHONE_AT )//AT
	{		   
	   ATCOMM_Handle_RecvData(m_RBuf,buffLen);   
	}
//.......其它功能的处理


}
	

 主要思想是通过当时的端口号和终端状态进行相应的数据处理。

 

问题:以后如果还需要添中新的功能模块,就需要在终端状态和数据处理中添加相应的代码,虽然添加的代码量不大,但要所设计模式的原则:

     找出应用中可能需变化之处,把他们独立开来,不要和那些不需要变化的代码混在一起。

 

       如果说MTK层的数据处理HandleMMIReceivedData就应该是不需要变化之处,每次的功能模块就是可能需要变化之处。那么就是要把他们独立开发。从几种设计模式应用中可以找出比较类似的一个模式,那就是观察者模式。

     在MTK中有一个是叫做消息注册,其本质也应该就是观察者模式。如果使用原来的消息注册,有一个问题就是一个应用要对应一个msg_id,那么通用性也不好。那就在原来消息注册的基础上,我们自己来实际观察者模式。以下是主要实现的测试代码:

// MessageTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string.h>

typedef void (*FuncPtr) (unsigned char *,unsigned int);


typedef struct
{
		int  port ;			//接收数据的端口
		FuncPtr        pHandleRecvFun; //处理接收到的数据的函数指针		
}xn_uart_handle_recv_struct;
	


 #define XN_MAX_UART_NUM 4		//现在终端最大的串口数

typedef struct
{
	int nUartCount ;		
	xn_uart_handle_recv_struct uartRecvStru[XN_MAX_UART_NUM];	
}xn_uart_handle_mode_struct;
	
  
xn_uart_handle_mode_struct g_uartHandleRecv;
/*
	本次处理主要是使用观察者模式,主要动作是注册和注销
*/

void XINO_TRACE(char *funName,char *tip)
{
	printf("fun is [%-30s],tip is: %s  \r\n",funName,tip);
}


//初始化
void XN_UartHandle_Init(void)
{	
	XINO_TRACE("XN_UartHandle_Init","init data ");

	memset((void *)&g_uartHandleRecv.nUartCount,0,sizeof(g_uartHandleRecv));

}

int XN_UartCheckPort(int  nIndex)
{
	if( 0>nIndex || (nIndex+1)>XN_MAX_UART_NUM ) //输入的序号不在正确的范围内
	{
		XINO_TRACE("XN_UartCheckPort","return -1");
		return -1;
	}
	
	XINO_TRACE("XN_UartCheckPort","return 1");
	return 1;
}

//查找
/*******************************************************************************
 * 函数名称: xn_uart_findbyport
 *     
 * 功能描述: 通过端口号查找
 *			
 * 参数说明: 
 *								
 *
 * 返 回 值: 
	>=0 找到了返回这个端口号在列表中的序号
	=-1 在列表中不存在
 *     
 * 历史记录: 
 *     日期: 2009-1-16       修改人linhai
 *     描述: 创建
*******************************************************************************/
int xn_uart_findbyport(int  nport)
{
	int i = 0;
	
	for(i=0;i<g_uartHandleRecv.nUartCount && i<XN_MAX_UART_NUM ;i++)
	{
		int nUartPort = g_uartHandleRecv.uartRecvStru[i].port;
		if(nUartPort==nport)
		{
			printf("fun is [xn_uart_findbyport] find by port %d index = %d\r\n ",nport,i);		
			return i;
		}

	}
	
	XINO_TRACE("xn_uart_findbyport","return -1");
	return -1;
} 


//更新
void xn_uart_update_callHandleFun(int nIndex,xn_uart_handle_recv_struct mUartRecvStru)
{

	g_uartHandleRecv.uartRecvStru[nIndex].port = mUartRecvStru.port;
	g_uartHandleRecv.uartRecvStru[nIndex].pHandleRecvFun = mUartRecvStru.pHandleRecvFun;
	printf("fun is [xn_uart_update_callHandleFun] update data index=%d port=%d after count is =%d\r\n",
		nIndex,mUartRecvStru.port,g_uartHandleRecv.nUartCount);
}

//添加
void xn_uart_add_callHandleFun(xn_uart_handle_recv_struct mUartRecvStru)
{
		
	int port = mUartRecvStru.port;
	int nIndex = 0;
	
	XINO_TRACE("xn_uart_add_callHandleFun","add data");

	if(XN_UartCheckPort(port)==-1)
	{
		return;
	}


	nIndex = xn_uart_findbyport(port);

	if(nIndex==-1)
	{
		if(g_uartHandleRecv.nUartCount>XN_MAX_UART_NUM)
		{
			return;
		}

		nIndex = g_uartHandleRecv.nUartCount;
	
		g_uartHandleRecv.nUartCount++;

	

	}

	xn_uart_update_callHandleFun(nIndex,mUartRecvStru);		

}

//删除
void xn_uart_dele_callHandleFun(int  nPort)
{
	int nIdex = -1;

		
	XINO_TRACE("xn_uart_dele_callHandleFun","dele by port");

	if(XN_UartCheckPort(nPort)==-1)
	{
		return;
	}

	nIdex = xn_uart_findbyport(nPort);
	if(nIdex==-1)
	{
		return;
	}
	else
	{	int i = nIdex;
		for(i;i<g_uartHandleRecv.nUartCount;i++)
		{
			g_uartHandleRecv.uartRecvStru[i].port =g_uartHandleRecv.uartRecvStru[i+1].port ;
			g_uartHandleRecv.uartRecvStru[i].pHandleRecvFun = g_uartHandleRecv.uartRecvStru[i+1].pHandleRecvFun;
		}
		g_uartHandleRecv.uartRecvStru[i].port =0;
		g_uartHandleRecv.uartRecvStru[i].pHandleRecvFun =NULL;
		g_uartHandleRecv.nUartCount--;
	}
		
	printf("xn_uart_dele_callHandleFun: g_uartHandleRecv.count = %d \r\n",g_uartHandleRecv.nUartCount);
}

 /*******************************************************************************
 * 函数名称: xn_uart_subscribe
 *     
 * 功能描述: 注册
 *			
 * 参数说明: 
 *								
 *
 * 返 回 值: void				
 *     
 * 历史记录: 
 *     日期: 2009-1-16       修改人linhai
 *     描述: 创建
*******************************************************************************/
void xn_uart_subscribe( int nport ,FuncPtr pFun )
{
	xn_uart_handle_recv_struct subscriber;
	subscriber.port = nport;
	subscriber.pHandleRecvFun = pFun;
	xn_uart_add_callHandleFun(subscriber);
		
}


  /*******************************************************************************
 * 函数名称: xn_uart_desubscribe
 *     
 * 功能描述: 注销
 *			
 * 参数说明: 
 *								
 *
 * 返 回 值: void				
 *     
 * 历史记录: 
 *     日期: 2009-1-16       修改人linhai
 *     描述: 创建
 *******************************************************************************/
 void xn_uart_desubscribe(int port)
{
	xn_uart_dele_callHandleFun(port);
}

void HandleMMIReceivedData(unsigned char port)
{
	FuncPtr mFun = NULL;
	int nIndex = 0;
	nIndex = xn_uart_findbyport(port);
	if (nIndex!=-1)
	{
		mFun = g_uartHandleRecv.uartRecvStru[nIndex].pHandleRecvFun;
		mFun((unsigned char *)"hello world",strlen("hello world"));
	}

}
 
void fun(unsigned char *data,unsigned int datalen)
{
	printf("\r\n handlerecv data fun %s\r\n",data);
	return;
}
 
int main(int argc, char* argv[])
{
	//---------------------
	xn_uart_handle_recv_struct temp;


	//--------------------------
	XN_UartHandle_Init();

	//
	printf("----------------begin test-----------------\n");
	temp.port =1;
	temp.pHandleRecvFun = fun;

	xn_uart_subscribe(temp);
	HandleMMIReceivedData(1);
	xn_uart_desubscribe(temp.port);
	
	
	printf("----------------end test-----------------\n");

	//
	return 0;
}

 附件是上面代码的工程。

 

       第三次修改的代码和原来相比修变不大,其本质也就是建立一个数据组,里面保存端口所对应的函数指针。在接收到数据后,从相应的端口中取出相应的函数指针。现在世界太平了,今后如果再有什么新的串口需求,只要专注了模块的功能实现,在需要使用的地方调用注册和注销接口。这样模块之间的独立性就实现了。

 

 

分享到:
评论

相关推荐

    C嵌入式编程设计模式(pdf 压缩)

    《C嵌入式编程设计模式》是一本专为嵌入式系统开发者编写的书籍,它以C语言为基础,结合面向对象的思想,深入探讨了在有限资源的嵌入式环境中如何高效、灵活地进行软件设计。这本书的目标是帮助读者理解和应用一系列...

    C嵌入式编程设计模式例程-3

    本例程主要关注的是C语言在嵌入式系统中的设计模式应用,特别是针对Linux环境的开发。 在嵌入式编程中,C语言通常被选择作为主要的编程语言,因为它的高效性、灵活性以及对硬件的直接访问能力。然而,随着系统的...

    利用设计模式编写嵌入式软件应用程序代码.rar

    在嵌入式软件开发中,设计模式是一种经过实践验证的解决方案,用于解决常见的编程问题,特别是在资源有限、性能要求高的环境中。本资料“利用设计模式编写嵌入式软件应用程序代码”旨在帮助开发者理解和应用设计模式...

    C嵌入式编程设计模式例程-5

    在"Chapter five"中,我们将深入探讨这些设计模式的具体实现和应用,结合C语言和Linux环境,理解如何在嵌入式系统中有效利用这些模式,提升代码质量,优化系统架构。每个模式都可能包括详细的示例代码,帮助读者更好...

    嵌入式软件缺陷模式

    嵌入式软件缺陷模式的探索和应用是一个深入的话题,涉及软件质量保证、软件测试以及故障诊断等多个方面。在当前计算机技术不断发展的背景下,嵌入式系统在我们的日常生活和工业生产中扮演着越来越重要的角色。安全...

    面向对象嵌入式gui研究和模式应用

    总的来说,面向对象的嵌入式GUI研究和模式应用是一个综合性的主题,涉及编程理论、系统设计和资源管理等多个方面。开发者需要深入理解面向对象编程的概念,同时熟悉嵌入式环境的特性,才能设计出高效、灵活且易于...

    设计模式:可复用面向对象软件的基础(非扫描版+高清)

    提到的资源不仅涵盖设计模式,还涉及到Linux、C++、Qt、嵌入式和Web等领域,这意味着这些资源可以帮助开发者在多个技术栈中应用设计模式,实现更高效、灵活的软件开发。 8. **学习路径建议** 对于初学者,可以从...

    设计模式-观察者模式-作业-observer.zip

    观察者模式(Observer Pattern)是软件设计模式中的行为模式之一,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于实现事件驱动或发布-...

    嵌入式原理与应用实验六ARM处理器工作模式实验

    嵌入式系统是计算机科学中的一个重要分支,它涉及到硬件和软件的紧密结合,以实现特定功能。在嵌入式系统中,ARM处理器因其高效能、低功耗的特点而被广泛使用。ARM处理器工作模式的理解和应用是开发嵌入式系统的关键...

    Qt设计模式(中英双语),附带源码

    **Qt中的设计模式应用** 1. **单例模式**:在Qt中,QApplication和QQmlEngine等类就是单例模式的应用,确保在整个程序中只有一个实例存在。 2. **工厂模式**:QFactoryInterface和QPluginLoader提供了一种动态创建...

    C++设计模式-基于QT4开源跨平台开发框架 源码

    在本资源中,"C++设计模式-基于QT4开源跨平台开发框架 源码",我们将重点探讨如何在C++编程语言中结合QT4框架来应用这些模式。 QT4是一个广泛使用的开源跨平台开发框架,它允许开发者用C++创建桌面、移动和嵌入式...

    嵌入式系统原理-课程设计改进交通灯.zip

    嵌入式系统原理在现代科技领域占据着至关重要的地位,特别是在交通管理中,它们通过高效、精准的控制来优化交通流量。本课程设计的主题是改进交通灯系统,它结合了硬件设计与软件编程,旨在让学生深入理解嵌入式系统...

    C++ Qt设计模式(第2版)

    7. **第二版更新**:相较于第一版,第二版可能会加入新的Qt版本特性、更新的设计模式应用以及来自社区的反馈和经验总结,以保持内容的时效性和实用性。 通过对《C++ Qt设计模式(第2版)》的深入学习,开发者不仅...

    C++Qt设计模式(第2版)

    结合设计模式,Qt的潜力可以得到更充分的发挥。 书中可能会涵盖以下主题: 1. **单例模式**:在Qt中,单例模式常用于确保类只有一个实例,例如QApplication或QSettings。书中会讲解如何正确实现和使用单例,以避免...

    C++ Qt设计模式(第2版)中文版

    《C++ Qt设计模式(第2版)》是一本深入探讨C++与Qt框架结合使用的专业书籍,旨在帮助读者理解并掌握如何在Qt环境中有效应用设计模式,提升软件开发的效率和质量。这本书中文版的发布,使得更多的国内开发者能够方便...

    GOF(四人帮)设计模式的官方资源

    总之,《GOF设计模式的官方资源》是软件开发者的宝贵财富,无论是在嵌入式领域还是其他面向对象编程中,深入理解和应用这些模式都能显著提升我们的设计能力和编程技巧。在实际项目中,结合STM32F103的特性,灵活运用...

    嵌入式系统导论英文版

    反馈控制是嵌入式系统设计中的一个核心概念。它涉及到根据系统输出来调整输入的过程,目的是使系统的实际行为接近期望的行为。反馈控制机制能够提高系统的鲁棒性和适应性,在各种工业自动化和控制领域都有广泛的应用...

    计算机三级嵌入式系统考前回顾(一).pdf

    嵌入式系统是计算机系统的一个重要分支,其主要特点是与特定的应用紧密结合,通常具有较小的体积、较低的功耗以及高可靠性和实时性等特点。在计算机三级嵌入式系统考前回顾中,将详细讨论嵌入式处理器的体系结构、...

Global site tag (gtag.js) - Google Analytics