45891 (665214), страница 2
Текст из файла (страница 2)
Пример использования шаблона
Напишем код для решения поставленной в начале статьи задачи.
#include #include using namespace std; #include "FiniteStateMachine.h" using namespace FSM; // Определим тип для событий enum Events { letter = 0, digit = 1 }; int main( int argc, char ** argv ) { #define FSMStateType string #define FSMEventType Events SFiniteStateMachine< StateType, EventType, SEmptyFunctor, SThrowStrategy > MyMachine( FSMBEGIN( "empty" ) FSMSTATES "empty" << "number" << "identifier" << "unknown" FSMEVENT(letter) "identifier" << "unknown" << "identifier" << "unknown" FSMEVENT(digit) "number" << "number" << "identifier" << "unknown" FSMEND ); #undef FSMStateType #undef FSMEventType cout << "StartState is: " << MyMachine << endl; MyMachine << digit << digit << letter; cout << "The 'unknown' state is expected. Current state is: " << MyMachine << endl; // Внимание: круглые скобки в следующей строке обязательны. Они обеспечат // правильный порядок выполнения операторов cout << "Reset the machine. Current state is: " << (MyMachine << ResetMachine) << endl; MyMachine << letter << digit << letter; cout << "The 'identifier' state is expected. Current state is: " << MyMachine << endl; return 0; } |
В примере намеренно опущены такие детали, как обработка исключений и введение функций, вызываемых при входе и выходе из состояния. Чтобы продемонстрировать возможность определения стратегий пользователя, в конструкторе MyMachine указаны все параметры, включая параметры по умолчанию.
Требования к клиентским приложениям
Требования немногочисленны. Для классов событий и состояний должны быть определены operator==, operator= и конструктор копирования. operator== используется для поиска событий и состояний в списках алгоритмом STL find. operator= используется при копировании элементов списков. Конструктор копирования используется при инициализации списков и других элементов.
Если клиент пользуется предоставленным функтором для вызова функций входа и выхода, то класс состояния должен реализовывать соответствующие функции: OnExit и OnEnter.
Преимущества и недостатки предложенного решения
Преимущества:
Шаблон строго типизирован. Это означает, что неправильно написанный код не будет принят компилятором, и ошибка не дойдет до времени выполнения программы.
Расширены понятия состояния и события. Теперь это произвольные классы, написанные пользователем.
Не используется оператор reinterpret_cast, способный привести к неправильным результатам.
Все описание автомата сосредоточено в одном месте. Нет привязки к последовательности описания реакций на события.
Гибкость поведения определяется пользовательскими функторами. Предоставляется набор уже готовых функторов.
Возможно динамическое создание описания конечного автомата. Например, можно создать экземпляры Proxy-классов, прочитать из файла описание автомата, а затем создать экземпляр SFiniteStateMachine.
Нет операций создания и удаления объектов с помощью операторов new и delete.
Нет никаких требований к классам состояний и событий (кроме возможности их сравнения).
Недостатки:
Много операций копирования при создании автомата. Однако этот недостаток отчасти компенсируется тем, что обычно автомат создается один раз, а используется многократно.
Надо писать две директивы препроцессора или использовать длинный префикс. Однако это лишь проблема набивки текста.
Лично я готов мириться с этим коротким списком недостатков ради полученных преимуществ.
Возможные пути усовершенствования шаблона
Внимательный читатель заметит, что можно увеличить гибкость и повысить производительность шаблона. В следующем списке перечислены улучшения, лежащие на поверхности:
Можно отказаться от промежуточного класса SFiniteStateMachineProxy. Это позволит сэкономить на копированиях, но внесет потенциальную возможность неправильного использования шаблона.
Можно ввести манипуляторы, которые позволят в явном виде при описании переходов указывать такие, которые надо игнорировать, или генерировать исключение при их появлении.
Потоковая безопасность
В шаблоне используются контейнеры STL, операции с которыми в многопоточной среде могут привести к проблемам. Поскольку при проектировании шаблона ставилась цель разработать независимое от платформы решение, то никаких средств синхронизации в шаблоне нет. Наличие средств синхронизации, как известно, в зависимости от ситуации может быть как достоинством, так и недостатком. Если они не нужны, их наличие только породит дополнительные накладные расходы. Добавить же средства синхронизации в шаблон опытному разработчику не составит труда.
Список литературы
C/C++ User’s Journal, May 2000
Booch G., Rumbaugh J., Jacobson I. The Unified Modeling Language User Guide. Addison-Wesley, 2001
Meyers S. Effective STL. Addison-Wesley, 2001
Alexandrescu A. Modern C++ Design. Addison-Wesley, 2002
Lewis P., Rosenkrantz D., Stearns R. Compiler Design Theory. Addison-Wesley, 1976
Schildt H. С/С++ Programmer’s Reference. Second Edition. Williams, 2000
Meyers S. Effective C++. Second Edition. Addison-Wesley, 1998 and More Effective C++. Addison-Wesley, 1996
Sutter G. Exceptional C++. Addison-Wesley, 2002
Для подготовки данной работы были использованы материалы с сайта http://www.rsdn.ru/