Класс Command
Для нашей проблемы характерна фундаментальная абстракция данных COMMAND, представляющая любую операцию, отличающуюся от Undo и Redo. Выполнение операции это лишь один из многих компонентов, применимых к команде, - команду можно сохранить, тестировать или отменить. Так что нам понадобится класс и вот его первоначальная форма:
deferred class COMMAND feature execute is deferred end undo is deferred end endКласс COMMAND описывает абстрактное понятие команды и потому должен оставаться отложенным. Фактические типы команды будут представлены эффективными потомками этого класса, такими как:
class LINE_DELETION inherit COMMAND feature deleted_line_index: INTEGER deleted_line: STRING set_deleted_line_index (n: INTEGER) is -- Устанавливает n номер следующей удаляемой строки do deleted_line_index := n end execute is -- Удаляет строку do "Удалить строку с номером deleted_line_index" "Записать текст удаляемой строки в deleted_line" end undo is -- Восстанавливает последнюю удаляемую строку do "Поместить deleted_line в позицию deleted_line_index" end endАналогичный класс строится для каждой команды класса.
Что же представляют собой такие классы? Экземпляр LINE_DELETION, как будет показано ниже, является небольшим объектом, несущим всю необходимую информацию, связанную с выполнением команды: строку, подлежащую удалению, (deleted_line) и ее индекс в тексте (deleted_line_index). Эта информация необходима для выполнения команды undo, если она потребуется, или для повтора redo.
Рис. 3.1. Объект command
Атрибуты, такие как deleted_line и deleted_line_index, у каждой команды будут свои, но всегда они должны быть достаточными для поддержки локальных операций execute и undo. Объекты, концептуально описывающие разницу между двумя состояниями приложения: предшествующим и последующим за выполнением команды, дают возможность удовлетворить требование U3 из нашего списка - хранить только то, что строго необходимо.
Структура наследования классов выглядит следующим образом:
Рис. 3.2. Иерархия классов COMMAND
Граф показан плоским ( все потомки COMMAND находятся на одном уровне), но ничто не мешает добавить некую структуру, группируя команды по типам, где каждая категория может иметь общие специфические черты.
При определении понятия важно указать, какие характеристики оно не покрывает. Здесь концепция команды не включает Undo и Redo; например, не имеет смысла выполнять откат самого Undo (если только не иметь в виду выполнение Redo). По этой причине в обсуждении используется термин операция (operation) для Undo и Redo и слово команда (command) для операций, допускающих откат и повтор, подобных вставке строки. Нет необходимости в классе, покрывающем понятие операции, так как такие операции, как Undo, имеют только одно связанное с ними свойство - быть выполненными.
Это хороший пример ограничений упрощенного подхода к "поиску объектов", подобному известному методу "Подчеркивание существительных", идея, изучаемая в последней лекции. В спецификациях проблемы существительные command и operation одинаково важны; но одно приводит к фундаментальному классу, второе - вообще не дает класса. Только изучение абстракций в терминах применимых операций и свойств может помочь в поиске классов проектируемой ОО системы. |