В первом случае архитектура системы скомпонована из ряда относительно независимых объектов, каждый из которых выполняется как поток управления. Можно было бы, например, создать несколько новых объектов-датчиков, построенных с помощью более примитивных абстракций, каждый из которых отвечал бы за считывание информации с определенного датчика и за передачу ее центральному агенту, обрабатывающему всю информацию. Подобная архитектура имеет свои преимущества и является, пожалуй, единственной приемлемой моделью в случае проектирования распределенной системы, которая должна производить обработку большого числа параметров, поступающих с удаленных датчиков. Эта модель также позволяет эффективнее оптимизировать процесс сбора данных (каждый объект-датчик может содержать в себе информацию о том, как надо приспосабливаться к изменению окружающих условий - увеличивать или уменьшать частоту опроса, например).
Однако подобные архитектуры оказываются не всегда приемлемыми при создании жестких систем реального времени, где требуется обеспечить предсказуемость процесса обработки. Метеорологическую станцию нельзя отнести к таким системам, но для нее, тем не менее, требуется определенная степень предсказуемости и надежности. По этой причине мы выбираем для нашей системы модель покадровой обработки.
Как показано на рис. 8-12, процесс мониторинга осуществляется в данном случае как последовательность считывания, обработки и вывода на экран значений параметров через определенные промежутки времени. Каждый элемент такой последовательности называется
На рис. 8-13 приведена диаграмма классов, отражающая особенности архитектуры системы. Здесь присутствуют, в основном, те же самые классы, которые были определены на этапе анализа. Главное отличие от предыдущих диаграмм состоит в том, что теперь мы видим, каким образом ключевые абстракции нашего программного приложения взаимодействуют друг с другом. Мы, естественно, не можем отразить на одной диаграмме все существующие классы и связи между ними. Здесь, например, не воспроизведена иерархия классов-датчиков.
Кроме того, мы ввели один новый класс Sensors, который служит для объединения в коллекцию всех объектов-датчиков. Поскольку по крайней мере два агента (Sampler и InputManager) в нашей системе должны ассоциироваться с целой коллекцией датчиков, помещение их в один контейнерный класс позволяет рассматривать все датчики единым образом.
Механизм покадровой обработки
Поведение нашей системы в основном определяется взаимодействием классов Sampler и Timer, поэтому, чтобы оправдать нашу модель, следует быть особенно внимательным при их описании.
Начнем с разработки внешнего интерфейса для класса Timer, осуществляющего диспетчеризацию функции обратного вызова (все решения будут в дальнейшем реализовываться на языке C++). Во-первых, с помощью ключевого слова typedef определим новый тип переменной, Tick, соответствующий словарю нашей проблемной области.
// Временной промежуток, измеряемый в 1/60 долях секундыtypedef unsigned int Tick
Затем определим класс Timer:
class Timer {public:
static setCallback(void (*)(Tick));static startTiming();static Tick numberOfTicks();
private:...};
Это - необычный класс хотя бы потому, что он содержит не совсем обычную информацию. Функция-член setCallback используется для передачи таймеру функции обратного вызова. Таймер запускается вызовом функции startTiming, после чего единственный экземпляр класса Timer начинает вызывать функцию обратного вызова каждую 1/60 секунды. Отметим, что функция запуска введена в явном виде, поскольку нельзя полагаться на то, как в частной реализации определяется порядок обработки объявлений.
Прежде чем перейти к классу Sampler, желательно ввести перечислимый тип всех датчиков, присутствующих в нашей системе, следующим образом:
// Перечисление названий датчиковenum SensorName {Direction, Speed, WindChill, Temperature, DewPoint, Humidity, Pressure};