设计模式在软件的应用

时间:2022-05-16 08:07:42

设计模式在软件的应用

1地面测发控软件需求分析

由图可知地面测发控软件主要包括主控软件、显示软件以及数据处理软件等。主控软件作为地面测发控系统的核心软件,主要完成测试流程控制、数据通讯存储等功能。为保证导弹/火箭在发射前功能正常、性能良好,保证安全、准时发射,需要对导弹/火箭进行全面、综合的测试,评估导弹/火箭性能。地面测发控软件中主控软件的测试流程控制功能即实现了导弹/火箭在发射前按预先设计好的时序进行各项功能和性能的测试,比如:总线误码率检查、系统配电自检、弹上时序检查等。测试流程按照功能及属性归类,可划分为不同的流程类,称之为主流程,每个主流程包含不同的流程项,称为子流程,每个子流程包含不可分割的流程步骤,简称为步序。操作手可根据要求选择相应的主流程或子流程进行系统测试。为验证系统各项测试的有效性,需要存储测试数据,以便事后进行数据分析。目前大部分型号主控软件均可以监听弹上通讯数据,并对数据进行处理和分析,如存盘、转发、提取消息、提取数据(伺服、电压及时序)等不同的功能。数据存储的运行不能影响程序的正常功能及性能,因此数据存盘采用低优先级的任务实现。显示软件主要负责显示测试数据,接收操作手按键输入,是操作手和主控软件之间的中介,实现了人机交互的功能;数据处理软件主要完成测试数据的处理、判读等功能。本文主要根据地面测发控软件的测试流程控制和数据存储的功能需求,讨论设计模式在地面测发控软件中的应用。

2设计模式在地面测发控软件中的应用

设计模式的有效复用是当前软件领域研究的重要内容,通过利用设计模式的思想来指导软件结构设计,不仅可以缩短软件设计和实现的周期,还可以提高软件的可维护性、可复用性。本文根据地面测发控软件的需求,使用命令模式、单件模式、观察者模式和主动对象模式解决地面测发控系统软件所面临的通用问题。

2.1命令模式在地面测发控软件的应用

测试流程控制模块负责对导弹/火箭发射前的各项功能进行全面测试,操作手选择某一流程项,系统将自动执行其所有步序。步序参数确定了步序的具体功能,如何将步序参数赋给步序,其中最直观的方法是,所有不同的步序共享同一类型的结构体,步序的调用则在步序类中有步序执行函数,根据步序参数结构体中的步序标记调用不同的步序函数,并以步序结构体单元作为参数。但这种方法使某个步序可以访问不需要的步序结构体字段,不符合面向对象的封装原则;步序函数所在类继承自同一抽象类,拥有步序执行函数,每增加或删除一个步序均要修改抽象类定义的步序执行函数,因此可扩展性差。为解决以上问题,本文采用命令模式进行程序设计。命令模式属于对象行为型模式,命令模式将一个请求封装为一个对象,并提供一致性发送请求的接口。当一个事件发生时,它不直接把事件传递到事件调用者,而是在命令和调用者之间增加一个中间者,将这种直接关系切断,同时两者之间都隔离。事件调用者只是和接口打交道,不和具体实现交互。以主控软件常用的延时功能为例,创建一个抽象的CFlowMethodCallBase类,该类包含1个公共接口call(),所有步序类均继承自该抽象类。另外,创建CFlowMethodCallBase类的子类CMethodCallDe-layTime,即步序类。该类包含1个call()方法,实现对CCtrlTime类的DelayTime()方法的引用,Delay-Time定义了具体的延时功能。步序的实现有了命令模式为基础,还要实现步序的管理和运行。首先是注册步序,在步序描述文件(XML)中保存步序的UUID号、名称、参数个数、参数名称和缺省值等信息,CMethodCallDelayTime类构造函数执行时将步序的UUID号通过哈希映射表与自身的指针关联起来。最后是步序的执行。通过步序创建器对象读取XML文件,从中提取CMethod-CallDelayTime类的UUID,再通过哈希表找到该类的指针,并将指针存储在数组中。由步序执行器对象,获取数组中的指针,即可调用相应的call()函数,实现对DelayTime步序的调用。步序执行器对象运行在自己独立的任务(线程)中,当主控软件收到测试开始指令后,立即启动该任务,步序执行器将逐项执行XML文件中的步序,直到所有步序执行完毕,或者收到暂停、停止指令。如图2所示,在测试流程控制模块中使用命令模式,并结合组合模式,能够简单快捷的进行测试流程管理,增加或删除某一步序,只需在CFlowMethod-CallBase父类下添加/删除具体的步序子类,并将该步序在XML文件中注册或删除即可。使用命令模式,将调用者和被调用者分离,实现了功能之间的解耦,符合低耦合、高内聚的思想,大大提高了软件的可维护性和扩展性。

2.2单件模式在地面测发控软件的应用

地面测发控软件的测试流程控制功能负责火箭/导弹射前各项功能和性能测试,测试项目达几十到几百个不等,按功能划分为步序甚至更多。需要创建一个测试流程管理类(CFlowManage类)的实例,引用CFlowManage类的RegisterItem()方法完成步序的注册。由于测试项目过多,每个步序类初始化都需要一个CFlowManage类的实例,增加了程序执行的复杂度。本文采用单件模式解决此项问题。单件模式属于创建型设计模式,它保证一个类仅有一个实例,并提供一个访问它的全局访问点,客户可以从一个众所周知的访问点访问它。ACE(AdaptiveCommunicationEnviron-ment)技术提供了单件模式的模板类,封装了单件模式的具体实现。使用ACE单件模式的模板创建CFlow-Manage类的一个指针CFlowManageSingleton,代码如下:TypedefACE_Singleton<CFlowManage,ACE_SYNCH_MUTEX>CFlowManageSingleton;CFlowManageSingleton指针只需通过Instance操作指向CFlowManage类的RegisterItem方法,即可完成步序的注册。代码如下:CFlowManageSingleton::instance()->Regis-terItem("XXXX",static_cast<CFlowMethodCallBase*>(this));类似的,界面显示功能也可以使用单件模式为界面显示类创建唯一的实例,可以在任何一个访问点访问类实例,调用界面显示类的方法,完成界面显示功能,提高了代码的灵活性。

2.3观察者模式在地面测发控软件的应用

目前各型号地面测发控软件均可以监听弹上通讯数据,并对数据进行处理和分析。当数据对象发生改变时,希望依赖于该数据对象的所有使用者都能立即被通知。本文采用观察者设计模式描述这种依赖关系。观察者设计模式定义了对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新[2]。通过使用观察者模式,系统可以独立的改变目标对象和观察者对象,提高目标对象和观察者的复用性。图3为观察者模式在地面测发控软件应用的结构图。对于被观察者,首先定义一个抽象的Subject类作为目标类,该类提供注册和删除观察者的接口。Subject类还定义了svc任务,该任务循环执行调用UpdateAllObserver方法,UpdateAllObserver方法包含观察者类Observer的一个引用,可将数据的变化通知给所有向其注册的观察者类。CRead1553BFrmUDP类作为Subject类的子类,是具体的目标类,该类的ReadBuffer()主要负责从总线接收数据,记录数据状态。对于观察者,首先定义一个抽象的Observer接口,所有监听数据变化的观察者均继承自该抽象类,比如SaveObserver类、AnalyseObserver类等,观察者将自己注册到目标类对象中,目标类将观察者类存放在一个list容器里。Observer类的子类实例化各自的Update方法可实现实时更新,以正确反应任务的执行情况。观察者模式降低了目标与观察者之间的耦合度。一个目标仅知道它有一系列观察者,而无需知道有多少个观察者及其归属类,它唯一的责任是通过UpdateAllObserver函数通知向它注册的各观察者。通知被自动广播给所有已向该目标对象登记的有关对象。

2.4主动对象模式在地面测发控软件的应用

数据存储的运行不能影响程序的正常功能及性能,在有的多任务操作系统中,低优先级的任务会被高优先级的任务中断,因此为了保证其他重要任务的运行,可以使用优先级较低的任务实现数据存储功能。本文采用主动对象设计模式,实现了以异步方式对数据存盘,为任务间的协作提供了解决方案。主动对象模式可以提供对象在自己的任务上下文中,采用看似常规的方法调用处于不同任务上下文对象的成员函数,但该函数不是在发起者,而是在被调用对象的任务上下文中执行。每个主动对象拥有私有的控制线程,用于执行客户在这个对象上调用的任何方法。当对象的方法调用需要很长时间才能完成时,主动对象模式就会派上用场,它可以把主控线程解放出来去做其它事情[4-6]。当主控软件的数据接收和处理等关键任务有数据需要存储在硬盘上时,采用主动对象模式提高关键任务的响应速度。关键任务调用数据存储功能后迅速返回并重新执行关键操作,由低优先级的数据存储任务完成具体的存盘工作。简而言之,就是由关键任务发起存盘动作,而具体存盘的动作由低优先级的存盘任务完成。图4主动对象模式的应用类图数据存储框架类图如图4所示。首先,定义一个方法请求类TFC_File_Savebin_Method类,该类继承自ACE_Method_Request,它以对象的形式封装了方法调用call()的对象,call()实现了数据存盘功能。方法请求对象是在主动对象的客户向发出请求时创建的。然后,定义主动对象类Log_Task类。该类继承自ACE_Task_Base,“持有”控制线程。主动对象类Log_Task需要重载svc()虚函数,在其中指明主动对象需要执行什么命令流程。一旦acti-vate()函数被调用,ACE_Task_Base类会在svc()方法中启动一个新的控制线程,在svc()中实现的流程将在主动对象拥有的线程中被执行。另外,将Log_Task类的svc()写成一个无限循环执行模式,这个循环会不断的处理命令消息。最后,定义一个者类Proxy_SaveFile,这个类是给客户使用的,它聚合了TFC_File_Savebin_Method类和Log_Task类的实现。Proxy_SaveFile类定义了一个方法请求类TFC_File_Savebin_Method对象,并将其插入激活队列enqueue()中。队列中的请求对象会在Log_Task类的svc()方法中被执行。客户只需调用者类Proxy_SaveFile的一个引用,即可完成数据存盘功能的异步执行。主动对象模式解除了方法调用和方法执行之间的耦合,即前一个线程的调用(方法对象入队列)和后一个线程的处理(方法对象出对列和call调用)解耦。对于数据存盘或日志存储等优先级较低的任务,采用主动对象模式,可以实现异步存盘功能,使得系统的并发处理性能大幅提升。

3结束语

结合地面测发控系统软件的通用模型及其功能需求,详细描述了命令模式、单件模式、观察者模式和主动对象模式在地面测发控软件设计开发中的应用,解决了传统软件设计中存在的问题。并且,将这4种设计模式组合在一起,初步实现了一个具有流程控制和数据存盘功能的系统框架,降低了地面测发控软件的耦合性,提高了软件的复用性、扩展性和可维护性。

作者:杨喆 马卫华 马颖劲 解月江 单位:北京航天自动控制研究所

上一篇:设计模式在系统软件的应用 下一篇:毕业设计模式初步研究