第 17 章 气象监测系统建模
本章要点
初始阶段:建立初始用例模型、建立初始领域模型
细化阶段:验证初始用例模型、修改领域模型
构造阶段:引入概念类、实现类,对领域模型进行迭代,得到设计模型
交付阶段:将设计类映射为代码,实现系统的功能
学习目标
熟悉 RUP 统一过程开发方法,用迭代和增量方式开发软件系统。
本章以气象监测系统为例,以 RUP 方法对实时控制系统进行增量和迭代分析,此例详
细演示了 RUP 过程、类设计过程、迭代和增量过程、建模方法。读者以本例为模板,采用
RUP 方法开发自己的系统。
17.1 初始阶段
气象监测系统由少数的几个类构成。通过面向对象的开发方法,演示了 RUP 统一过程
的基本原则、增量和迭代方法、系统分析、设计、建模方法。
17.1.1 气象监测站需求
本系统通过传感器实现各种气象条件的自动采样、检测。要采样和测量的数据如下:
风速和风向
温度
气压
湿度
系统应该提供一个设置当前时间和日期的方法,以便报告过去 24 小时内 4 种主要测量
数据的最高值和最低值。
同时,系统还应通过上面的数据导出下面的数据:
风冷度;
露点温度;
温度趋势;
气压趋势;
系统还应该提供一个显示屏,每隔一个时间段,刷新上面 8 个主要数据,同时显示当
前的日期和时间。用户可以通过键盘选择某一个主要测量指标(如,温度、湿度),让系
统显示该测量指标在 24 小时内的最高值和最低值,以及出现这些值的时间。
系统应该允许用户根据已知值来校正传感器,并允许用户设置当前的时间和日期。
1
17.1.2 定义问题的边界
在对软件系统进行分析和设计之前,首先必须确定硬件平台,我们做以下假定。
处理器(即 CPU)采用 PC 或手持设备;
时间和日期由一个时钟提供;
通过远端的传感器来测量温度、气压和湿度;
用一个带有风向标(能感知 16 个方向中任意方向的风)和一些风杯(进行计
数的计数器)的标柱测量风向和风速;
通过键盘提供用户输入;
显示器是一个 LCD 图形设备;
计算机每 1/60 秒产生一次定时器中断。
图 17-1 展示了这个硬件平台的部署图。这是分析阶段的部署图。
<
>
keypad
<>
Clock
<>
Graphics Display
<>
Wind-direcction Sensor
<>
CPU
<>
Wind-speed Sensor
<>
Temperature Sonsor
<>
Humidity Sensor
<>
Pressure Sensor
图 17-1 硬件平台部署图
面向对象的开发方法,最关键之处在于抽取问题领域中的类。即,设计软件类,以模
拟硬件设备。例如,可以设计一个简单的时间日期类(TimeDate),以跟踪当前的日期和
时间。包括时、分、秒、日、月和年。
时间和日期类的责任必须包括设定日期和时间。为了完成这个责任,需要提供一些操作
来 设 置 时 间 和 日 期 , 通 过 操 作 :setHour 、setMinute 、setSecond 、setDay 、setMonth 和
setYear 来满足用户的需求。(通过对象的职责分析,识别类应该包含的操作)
根据前面的分析,我们设计出日期和时间类:
类名: TimeDate
责任:跟踪当前的时间、日期。
操作:
currentTime
currentDate
setFormat
setHour
setMinute
setSecond
setMonth
setDay
setYear
属性:
time
2
date
TimeDate 对象有两种状态:初始化状态和运行状态(运行在 24-hour mode 状态下)。
进入初始化状态时,系统重新设置对象的 time 和 date 属性值,然后无条件地进入运行状
态。运行状态是个复合状态,里面有两个子状态。在运行状态下,setFormat 操作可以实现
12-hour mode 和 24-hour mode 之间切换。无论对象处于哪种模式,设置时间和日期都会引
起对象重新初始化它的属性(本段是对 TimeDate 对象的状态变化的分析)。
set time or date / normalize value
Initializing
entry/On Entry / reset time and date
Runing
12-hour mode
12-hour mode
setFormat
24-hour mode
24-hour mode
current time or date / calculate string value
图 17-2 TimeDate 对象状态图
下面设计一个温度传感器类,模拟温度传感器。通过对温度传感器的初步分析,设计
出温度传感器类:
类名:Temperature Sensor
责任:跟踪当前温度。
操作:
currentTemperature
setlowTemperature
sethighTemperature
属性:
temperature
现在,假定每个温度传感器值用一个定点数表示,它的低点和高点可以校正到适合已
知的实际值,在这两点之间用简单的线性内插法将中间的数字转换为实际的温度,如图
17-3 所示。
40°
20°
实
际
温 10°
度
0°
●
-10°
-20°
高值●
低值
传感器值
3
图 17-3
Temperature 传感器校正
系统中已经有了实际的温度传感器,为什么还要声明一个类来模拟实际的温度传感器
呢?因为,在这个系统中,我们已经知道要多次使用这个对象,为了降低软件与硬件的耦
合度,我们的策略是,设计一个 Temperature Sensor 类。实际上,特定系统中温度传感器的
数目与软件的体系结构关系不大。通过设计一个 Temperature Sensor 类,可以使得这个系统
的其他成员的能够简单的操作任意数目的传感器。
同理,通过分析,下面得出气压传感器的规格说明:
类名:Pressure Sensor
责任:跟踪当前气压
操作:
surrentPressure
setlowPressure
sethighPressure
属性:
pressure
在前面需求分析中,系统要求报告温度和气压变化趋势,但是,我们在对温度和气压
设计时,遗漏了这个要求。
为了把这个要求补充到这两个类中。对 Temperature Sensor 类和 Pressure Sensor 类,可
以用-1 和 1 之间的浮点数来表达变化趋势,这些数字表示某个时间区间上,若干个数值的
一条拟合直线的斜率。因此,在这两个类中增加以下的责任和其相应的操作。
责任:报告温度或压力变化趋势,表示给定时间区间上,过去值的拟合直线的斜率。
操作:trend
trend 操作是 Temperature Sensor 类和 Pressure Sensor 类共有的行为,建议创建一个公
共的超类 Trend Sensor 负责提供这个共同行为。
在以前的设计中,多个传感器的共同行为作为传感器类本身的一个责任。其实,也可
以把这个共同行为作为某个外部代理类的责任,通过代理定期查询所有的传感器,然后计
算出每个传感器测量的数据变化趋势,这种设计比较复杂,往往很少采用。
通过初步分析,设计出湿度传感器类的规格说明如下。
类名:Humidity Sensor
责任:跟踪当前湿度,表示为百分比,范围是 0%~100%。
操作:
currentHumidity
setlowHumidity
sethighHumidity
属性:
humidity
Humidity sensor 类中,没有提供计算湿度变化趋势的责任。
在前面的系统分析时,一些行为是类 Temperature Sensor、Pressure Sensor 和 Humidity
Sensor 共有的。比如说,系统要求传感器提供一种方式来报告过去 24 小时内每种测量数据
的最高值和最低值。所以,建议创建一个公共的超类 Historical Sensor,负责提供这个公共
的行为。下面是这个超类的规格说明。
类名:Historical Sensor
责任:报告过去 24 小时内测量数据的最高和最低值
操作:
highValue
lowValue
timeOfhighValue
timeOflowValue
根据前面的分析,下面设计出风速传感器类。
4
类名:WindSpeed Sensor
责任:跟踪当前风向
操作:
currentSpeed
setlowSpeed
sethighSpeed
属性:
speed
因为不能够直接探测出当前的风速。风速的计算方法是:将标柱上风杯的旋转次数除
以计数间隔,然后乘以与特定的标柱装置对应的比例值。
对上面 4 个具体类(温度传感器、压力传感器、湿度传感器和风速传感器)做快速的
领域分析,可以发现它们有一个共同的特点,那就是可以根据两个已知的数据点,用线性
内 插 法 来 校 正 自 己 。 为 了 给 四 个 类 中 提 供 这 个 行 为 , 可 以 创 建 一 个 更 高 一 级 的 超 类
Calibrating Sensor(校正传感器)来负责这个行为,它的规格说明如下。
类名:Calibrating Sensor
责任:给定两个已知数据点,提供线性内插值的值
操作:
currentValue
setlowValue
sethighValue
Calibrating Sensor 类是 Historical Sensor 类的直接超类。
风向传感器既不需要校正,也不需要报告历史趋势。下面是这个类的设计。
类名:Winddirection Sensor
责任:跟踪当前风向,表达为罗盘图上的点。
操作:currentDirection
属性:direction
为 了 将 所 有 的 传 感 器 类 组 织 成 一 个 层 次 结 构 , 创 建 抽 象 基 类 Sensor , 该 类 作 为
Winddirection Sensor 和类 Calibrating Sensor 的直接超类。图 17-4 说明了这个完整的层次结
构。
5
Sensor
Calibrating Sensor
+currentValue()
+setHighValue()
+setLowValue()
WindDirection Sensor
+directoon
+currentDirection()
Historical Sensor
+highValue()
+lowValue()
+timeOfHighValue()
+timeOfLowValue()
Humidity Sensor
-humidity
+currentHumidity()
Trend Sensor
+trend()
WindSpeed Sensor
-speed
+currentSpeed()
Temperature Sensor
Pressure Sensor
-temperature
+currentTemperature()
-pressure
+currentPressure()
图 17-4 传感器类层次结构
下面设计边界类,它们是:小键盘类、显示器类、时钟类。
小键盘的规格说明如下。
类名:Keypad
责任:跟踪最近一次用户输入
操作:lastKeyPress
属性:key
值得注意的是,这个键盘仅仅知道几个键中的某个键被按下,把解释每个键的含义的
责任委托给其它的不同的类。
图 17-5 提供了一个通用的显示界面原型。在这个原型中,省略了对系统需求中的风冷
度和露点,也没有显示在过去 24 小时内主要测量数据的最高值或最低值的细节。同时,需
求提出某些显示模式:某些数据需要用文本显示(以两种不同的大小和两种不同的风
格)、某些数据用圆和线条显示(粗细不同);需求还要求,一些元素是静态的(如 temp
标签),另外一些元素是动态的(如风向)。在分析阶段,初步决定用软件来显示这些静
态和动态元素。
6
DATE:6-10-2005
TIME:13:56:42
TEMPERATURE:14 ℃
PRESSURE:29.96
HUMIDITY:38%
W
N
S
W
N
NE
7 pkh
SPEED
E
SE
S
图 17-5 气象监测系统显示面板
LCD(显示类)的规格说明如下。
类名:LCD Device
责任:管理 LCD 设备,为显示某些图形元素提供服务。
操作:
drawText
drawLine
drawCircle
settextSize
settextStyle
setpenSize
正像 keypad 类一样, LCDdevice 对象并不知道它所操纵的元素含义,该类对象仅仅知
道怎样显示文字和直线,而不知道这些图形代表什么含义。以这种方式来设计 LCD 类时,
必须提供一个代理来负责将传感器数据转换为显示器可以识别的数据。这个代理的设计,
推迟在后面实现。
最后一个需要设计的边界类是定时器。这里假定系统中有且只有一个定时器,它每隔
1/60 秒向计算机发出中断,调用一个中断服务例程。
图 17-6 演示了时钟对象与客户之间的交互。从图中可以看出,定时器如何和他的客户
协作:首先,客户提供向时钟发出一个回调函数,然后每隔 1/60 秒定时器调用这个函数。
在这种方式中,客户不必知道如何去截取定时事件,定时器也不必知道,当一个定时事件
出现时该怎么去做。这个协议要求客户必须在 1/60 秒之内执行完其回调函数,否则定时器
将错过一个事件。
7
aClient:Client
Timer
设置回调函数
1 : setCallback()
每1/60秒,一个硬件
中断被Timer类拦截,
Timer类随后分派客户
提供的回调
2
3
4
5
{1/60 秒}
图 17-6 时钟与客户之间的交互
时钟类的规格说明如下。
类名:Tmer
责任:截取定时事件,相应分派回调函数
操作:setCallBack
17.1.3 系统用例
现在,从客户观点来考察系统的功能。这里直接列出系统用例。如图 17-7 所示。
Monitor Weather Measurements
Monitor Derived Measurements
User
Display Max and Min value of Measurements
Power On
Calibrate Sensor
Set Date and Time
图 17-7 用例图
8