internal是内部的意思,linktableInternal.h被linktable.h引用,linktable.h被linktable.c引用,linktable.c被menu.c引用。
linktableInternal.h:linkTable结构体是链表,包含链表头、尾结点,以及一个int型存储链表中节点值之和,还有一个互斥变量mutex;文件里也定义了链表结点结构体LinkTableNode,这里只声明要有最基本的属性即指向下一个LinkTableNode的指针pNext。
linktable.h:由linkTable和LinkTableNode定义新结构体tLinkTableNode和tLinkTable,这个文件里基于这两个新结构体规定了要实现的链表应该实现哪些方法,包括删除链表、添加结点、删除结点、查抄结点、获取头、尾结点。如果希望链表实现另一套方法,可以仿照linktable.h包含linktableInternal.h,写另一套接口。
Callback函数需要一个Call-in函数,在这个例子里的接口定义如下
/*
* Search a LinkTableNode from LinkTable
* int Conditon(tLinkTableNode * pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
其中放在参数位置的函数Condition允许用户自定义,通过这个办法实现了用户自定义查询条件,以在链表中查询结点的功能,在linktable.c中通过如下代码做到这一点:
/*
* Search a LinkTableNode from LinkTable
* int Condition(tLinkTableNode * pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable,
int Condition(tLinkTableNode * pNode, void * args),
void * args)
{
if(pLinkTable == NULL || Condition == NULL)
{
return NULL;
}
tLinkTableNode * pNode = pLinkTable->pHead;
while(pNode != NULL)
{
if(Condition(pNode, args) == SUCCESS)
{
return pNode;
}
pNode = pNode->pNext;
}
return NULL;
}
在menu.c中定义了查询条件如下:
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
并在findCmd函数中用到了这个“在链表中按照给定查询条件查询结点”的功能:
/* find a cmd in the linklist and return the datanode pointer */
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)cmd);
}
FindCmd调用SearchCondition,要把自己的参数传给后者,可以选择①不给SearchLinkTableNode及其接口Condition加参数,声明一个全局变量,随用随赋值;②增加参数,在FindCmd函数体里把cmd链表指针传给SearchLinkTableNode。
根据如下集中耦合定义,①属于公共耦合,两个函数通过公共可访问的变量协作;②属于标记耦合,虽然显式传递的不是基本数据类型而是指针,但耦合度也比公共耦合低。
公共耦合
- 当软件模块之间共享数据区或变量名的软件模块之间即是公共耦合,显然两个软件模块之间的接口定义不是通过显式的调用方式,而是隐式的共享了共享了数据区或变量名。
数据耦合
- 在软件模块之间仅通过显式的调用传递基本数据类型即为数据耦合。
标记耦合
- 在软件模块之间仅通过显式的调用传递复杂的数据结构(结构化数据)即为标记耦合,这时数据的结构成为调用双方软件模块隐含的规格约定,因此耦合度要比数据耦合高。但相比公共耦合没有经过显式的调用传递数据的方式耦合度要低。
概括一下“查找cmd链表”这个功能体现的接口设计分层:
- linktableInternal.h基本链表结构
- linktable.h定义链表需要实现的函数,在这一层定义了call-in、callback函数的接口
- linktable.c实现链表函数和call-in函数(定义它根据callback函数的情况如何做出反应)
- menu.c使用链表函数,并定义callback函数
作者:255