для всех трех классов:
Отвественность:
Генерация сообщений о максимальных и минимальных значениях параметров за 24-часа.
Операции:
highValue - максимальное значение lowValue - минимальное значение timeOf HighValue - время, соответствующее максимальному значению timeOfLowValue - время, соответствующее минимальному значению
Пока отложим решение вопроса о том, как реализовать эту ответственность; мы вернемся к нему на этапе проектирования. Однако, учитывая то, что данное поведение является общим для всех трех датчиков, представляется целесообразным организация еще одного суперкласса, который мы назовем HistoricalSensor. Класс HumiditySensor является прямым потомком класса HistoricalSensor, так же как и TrendSensor. Последний служит промежуточным абстрактным классом, переходным между абстрактным HistoricalSensor и конкретными TemperatureSensor и PressureSensor.
Абстракция для датчика скорости ветра может выглядеть следующим образом:
Имя:
WindSpeedSensor
Ответственность:
Поддержание информации о текущей скорости ветра.
Операции:
currentSpeed - текущая скорость setLowSpeed - установка минимальной скорости setHighSpeed - установка максимальной скорости
Атрибуты:
speed - скорость
Требования к системе не предполагают возможности получения скорости непосредственно от датчика; текущая скорость ветра должна определяться как отношение числа оборотов на счетчике к величине интервала времени, за которое производились измерения. Полученное число затем надо умножить на калибровочный коэффициент, значение которого определяется конструкцией измерительного устройства. Этот алгоритм должен быть, естественно, реализован внутри класса. Клиенты не должны заботиться о том, каким образом посчитана текущая скорость ветра.
Краткий анализ последних четырех классов системы (TemperatureSensor, PressureSensor, HumiditySensor и WindSpeedSensor) показывает, что у них имеется еще одна общая черта: калибровка измеренных значений посредством линейной интерполяции. Вместо того, чтобы реализовывать эту способность по отдельности в каждом из классов, можно выделить особый суперкласс CalibratingSensor, ответственный за выполнение калибровки.
Ответственность:
Обеспечение линейной интерполяции значений, лежащих в известном интервале.
Операции:
currentValue - текущее значение setLowValue - установка минимального значения setHighValue - установка максимального значения
CalibratingSensor является непосредственным суперклассом для класса HistoricalSensor.
Последний рассматриваемый датчик - датчик определения направления ветра - несколько отличается от всех остальных, так как он не нуждается ни в калибровке, ни в вычислении минимальных и максимальных значений. Мы можем определить данную абстракцию следующим образом:
Имя:
WindDirectionSensor
Ответственность:
Поддержание информации о текущем направлении ветра, указываемом как точка на розе ветров.
Операции:
currentDirection - текущее направление
Атрибуты:
direction - направление
Чтобы объединить все классы, относящиеся к датчикам, в одну иерархию, имеет смысл создать еще один абстрактный базовый класс Sensor, который является непосредственным суперклассом для WindDirectionSensor и CalibratingSensor. Рис. 8-4 иллюстрирует полную иерархию классов датчиков.
Абстракция ввода информации с клавиатуры имеет следующий простой вид:
Имя:
Keypad
Ответственность:
Поддержание информации о коде последней клавиши, нажатой на клавиатуре.
Операции:
lastKeyPress - последняя нажатая клавиша
Атрибуты:
key - клавиша
Заметим, что этот класс не знает о назначении той или иной клавиши: экземпляр данного класса несет информацию лишь о том, какая клавиша была нажата. Ответственность за интерпретацию клавиш несет другой класс, который будет определен позднее.
Следующая абстракция - класс LCDDevice, предназначенный для того, чтобы обеспечить определенную независимость нашей программной системы от аппаратной части, на которой она будет работать. Для рабочих станций и персональных компьютеров существует целый ряд стандартов (хотя зачастую и конфликтующих между собой) графического интерфейса, таких, например, нет общепризнанных стандартов, поэтому анализ задачи приводит нас к мысли о том, что для ее решения необходимо создать прототипы и затем определить основные требования к интерфейсу пользователя.
На рис. 8-5 приведен один из подобных прототипов. Здесь не показаны изображения, характеризующие коэффициент резкости погоды и точку росы, требуемые в задании, а также такие детали, как верхние и нижние границы измерений за 24 часа. Однако, все основные графические элементы присутствуют. Итак, нам необходимо выводить на экран текст (двух различных размеров и начертаний), окружности и линии различной толщины. Также следует заметить, что некоторые элементы изображения являются статическими (такие, как заголовок ТЕМПЕРАТУРА), а некоторые - динамическими (направление ветра). И статические, и динамические элементы изображения генерируются программно. В итоге упрощается аппаратная часть (не надо заказывать специальные жидкокристаллические дисплеи со встроенными статическими элементами), но несколько усложняется программное обеспечение.
Требования к графике можно выразить через следующую абстракцию:
Имя:
LCDDevice
Ответственность:
Управление выводом на экран графических элементов.
Операции:
drawText - рисовать текст drawLine - рисовать линию drawCircle - рисовать окружность setTextSize - установка размера текста setTextStyle - установка начертания текста setPenSize - установка ширины линии