Состояние как класс
Пример "состояния" является типичным. Такой тип данных, играющий всеобъемлющую роль в передаче данных между программами, является первым кандидатом на роль модуля в ОО-архитектуре, основанной на классах (абстрактно описанных типах данных).
Понятие состояния было важным в оригинальной постановке проблемы, но затем в функциональной архитектуре эта важность была утеряна, - состояние было представлено обычной переменной, передаваемой из программы в программу, как если бы это было существо низкого ранга. Мы уже видели, как оно отомстило за себя. Теперь мы готовы предоставить ему заслуженный статус. STATE должно быть классом, одним из властителей структуры в нашей новой ОО-системе.
В этом классе мы найдем все операции, характеризующие состояние: отображение соответствующего экрана (display), анализ ответа пользователя (read), проверку ответа (correct), выработку сообщения об ошибке для некорректных ответов (message), обработку корректных ответов (process). Мы должны также включить сюда execute_state, выражающее последовательность действий, выполняемых всякий раз, когда сессия достигает заданного состояния (поскольку данное имя было бы сверхквалифицированным в классе, называемом STATE, заменим его именем execute).
Возвращаясь к рисунку, отражающему функциональную декомпозицию, выделим в нем множество программ, принадлежащих классу STATE.
Рис. 2.6. Компоненты класса STATEКласс имеет следующую форму: ...class STATE feature input: ANSWER choice: INTEGER execute is do ... end display is ... read is ... correct: BOOLEAN is ... message is ... process is ... end
Компоненты input и choice являются атрибутами, остальные - подпрограммами (процедурами и функциями). В сравнении со своими двойниками при функциональной декомпозиции подпрограммы потеряли явный аргумент, задающий состояние, хотя он появится другим путем в клиентских вызовах, таких как s.execute.
В предыдущих подходах функция execute (ранее execute_state) возвращала пользовательский выбор следующего шага. Но такой стиль нарушает правила хорошего проектирования. Предпочтительнее сделать execute командой. Запрос "какой выбор сделал пользователь в последнем состоянии?" доступен благодаря атрибуту choice. Аналогично, аргумент ANSWER подпрограмм уровня 1 заменен теперь закрытым атрибутом input. Вот причина скрытия информации: клиентскому коду нет необходимости обращаться к ответам помимо интерфейса, обеспечиваемого компонентами класса.