周立功教你学程序设计技术:做好软件模块的分层设计,回调函数要这样写
第二章为程序设计技术,本文为2.1.3 回调函数。
>>>> 2.1.3 回调函数
>>> 1. 分层设计
分层设计就是将软件分成具有某种上下级关系的模块,由于每一层都是相对独立的,因此只要定义好层与层之间的接口,从而每层都可以单独实现。比如,设计一个保险箱电子密码锁,其硬件部分大致包括键盘、显示器、蜂鸣器、锁与存储器等驱动电路,因此根据需求将软件划分为硬件驱动层、虚拟层与应用层三大模块,当然每个大模块又可以划分为几个小模块,下面将以键盘扫描为例予以说明。
(1)硬件驱动层
硬件驱动层处于模块的最底层,直接与硬件打交道。其任务是识别哪个键按下了,实现与硬件电路紧密相关的部分软件,更高级的功能将在其它层实现。虽然通过硬件驱动层可以直达应用层,由于硬件电路变化多样,如果应用层直接操作硬件驱动层,则应用层势必依赖于硬件层,则最好的方法是增加一个虚拟层应对硬件的变化。显然,只要键盘扫描的方法不变,则产生的键值始终保持不变,那么虚拟层的软件也永远不会改变。
(2)虚拟层
它是依据应用层的需求划分的,主要用于屏蔽对象的细节和变化,则应用层就可以用统一的方法来实现了。即便控制方法改变了,也无需重新编写应用层的代码。
(3)应用层
应用层处于模块的最上层,直接用于功能的实现,比如,应用层对外只有一个"人机交互"模块,当然内部还可以划分几个模块供自己使用。三层之间数据传递的关系非常清晰,即应用层->虚拟层->硬件驱动层,详见图 2.2,图中的实线代表依赖关系,即应用层依赖于虚拟层,虚拟层依赖于硬件驱动层。基于分层的架构具有以下优点:
降低系统的复杂度:由于每层都是相对独立的,层与层之间通过定义良好接口交互,每层都可以单独实现,从而降低了模块之间的耦合度;
隔离变化:软件的变化通常发生在最上层与最下层,最上层是图形用户界面,需求的变化通常直接影响用户界面,大部分软件的新老版本在用户界面上都会有很大差异。最下层是硬件,硬件的变化比软件的发展更快,通过分层设计可以将这些变化的部分独立开来,让它们的变化不会给其它部分带来大的影响;
有利于自动测试:由于每一层具有独立的功能,则更易于编写测试用例;
有利于提高程序的可移植性:通过分层设计将各种平台不同的部分放在独立的层里。比如,下层模块是对操作系统提供的接口进行包装的包装层,上层是针对不同平台所实现的图形用户界面。当移植到不同的平台时,只需要实现不同的部分,而中间层都可以重用。
图 2.2 三层结构示意
应用层处于模块的最上层,直接用于功能的实现,比如,应用层对外只有一个"人机交互"模块,当然内部还可以划分几个模块供自己使用。三层之间数据传递的关系非常清晰,即应用层->虚拟层->硬件驱动层,详见图 2.2,图中的实线代表依赖关系,即应用层依赖于虚拟层,虚拟层依赖于硬件驱动层。基于分层的架构具有以下优点:
降低系统的复杂度:由于每层都是相对独立的,层与层之间通过定义良好接口交互,每层都可以单独实现,从而降低了模块之间的耦合度;
隔离变化:软件的变化通常发生在最上层与最下层,最上层是图形用户界面,需求的变化通常直接影响用户界面,大部分软件的新老版本在用户界面上都会有很大差异。最下层是硬件,硬件的变化比软件的发展更快,通过分层设计可以将这些变化的部分独立开来,让它们的变化不会给其它部分带来大的影响;
有利于自动测试:由于每一层具有独立的功能,则更易于编写测试用例;
有利于提高程序的可移植性:通过分层设计将各种平台不同的部分放在独立的层里。比如,下层模块是对操作系统提供的接口进行包装的包装层,上层是针对不同平台所实现的图形用户界面。当移植到不同的平台时,只需要实现不同的部分,而中间层都可以重用。
>>> 2. 隔离变化
(1)好莱坞原则(Hollywood)
类似键盘扫描这样的模块,其共性是各层之间的调用关系,不可能随着时间而改变,即便上下层之间形成依赖关系,采用直接调用方式是最简单的。为了降低层与层之间的耦合,层与层之间的通信必须按照一定的规则进行。即上层可以
- 电源软启动的实用设计技巧(07-16)
- 周立功:动态分布内存——malloc()函数与calloc()函数(07-22)
- 周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数(07-25)
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 算法的泛化问题,这些坑你可能都经历过!|周立功教你学软件设计(08-01)
- 所有C语言数组和指针的知识都在这里了!|周立功手把手教你学C语言编程(08-01)