|
Программирование >> Разработка устойчивых систем
Также встречается термин программирование, управляемое события.ми . - Ilpimeu. перев. macro.add(new World): macro.add(new lAm): macro.runО: } III:- Команда предназначена прежде всего для передачи нужного действия функции или объекту. В приведенном примере это позволяет создать очередь операций для последующего выполнения. Иначе говоря, поведение программы формируется динамически - обычно для этого приходится писать новый код, но в данном случае задача решается простой интерпретацией сценария, хотя при выполнении очень сложных операций лучше воспользоваться паттерном Интерпретатор (Interpreter). В БЧ сказано: Команды представляют собой объектно-ориентированную замену для функций обратного вызова . Однако мы считаем, что в концепции функций обратного вызова слово обратный играет очень важную роль - в будущем управление возвращается стороне, создавшей функцию обратного вызова. С другой стороны, объект Команды просто создается и передается некоторой функции или объекту, и в дальнейшем вы с ним никак не связаны. Стандартный пример применения Команды -- реализация отката в приложениях. Каждый раз, когда пользователь выполняет какую-нибудь операцию, в очередь отката заносится соответствующий объект Команды. Выполнение этого объекта возвращает состояние программы на один шаг назад. Команда и смягчение привязки при обработке событий Как вы узнаете из следующей главы, одна из причин для реализации концепции многопоточности заключается в том, что она упрощает событийное программиро-вание\ когда поведение программы определяется непредсказуемо возникающими событиями. Например, если пользователь нажимает кнопку Quit во время выполнения продолжительной операции, он рассчитывает, что программа достаточно быстро отреагирует на его действие. В пользу многопоточности говорит и то, что многопоточность смягчает жесткую привязку между фрагментами программы. Другими словами, если вы запустите отдельный программный поток для отслеживания событий на кнопке Quit, то обычным операциям ничего не нужно знать об этой кнопке или других выполняемых операциях. Проблемы с жесткой привязкой также можно решить при помощи паттерна Команда. Любая обычная операция должна периодически вызывать функцию проверки состояния событий, в то же время при использовании паттерна Команда о проверяемых условиях ей знать ничего не нужно; тем самым операция перестает жестко привязываться к коду обработки событий: : C10:MulticastCommand.cpp {RunByHand} Смягчение привязки к коду обработки событий с применением паттерна Команда. #1nclude <1ostream> include <vector> iinclude <string> #include <ctime> #include <cstdlib> using namespace std; Иерархия классов для выполнения задач: class Task { public: virtual void operationO = 0: class TaskRunner { static vector<Task*> tasks: TaskRunnerO {} Синглетный класс TaskRunnerS operator=(TaskRunner&); Запрет TaskRunner(const TaskRunnerS); Запрет static TaskRunner tr; public: static void addCTaskS t) { tasks.push back(St); } static void run() { vector<Task*>::iterator it - tasks.beginO; while(it != tasks.endO) (*it++)->operation(); TaskRunner TaskRunner::tr; vector<Task*> TaskRunner::tasks: class EventSimulator { clock t creation: clock t delay; public: EventSimulatorO : creation(clock()) { delay = CL0CKS PER SEC/4 * (randO 20 + 1); cout delay = delay endl; bool firedО { return clockO > creation + delay: Источник асинхронных событий: class Button { bool pressed; string id; EventSimulator e: Для демонстрации public: ButtonCstring name) : pressed(false), id(name) {} void pressO { pressed = true; } bool isPressedO { if(e.firedO) pressO: Имитация события return pressed; friend ostreamS operator (ostreamS os. const Buttons b) { return OS b.id; Объект Команды class CheckButton : public Task { Buttons button: bool handled: public: CheckButton(Button S b) : button(b). handledCfalse) {} void operationО { if(button.isPressedO SS !handled) { cout button pressed endl: handled = true: Процедуры, выполняющие основные вычисления. Должны периодически прерываться для проверки состояния кнопок или других событий: void procedurelO { Выполнение операций procedurel. ... TaskRunner::run(): Проверка всех событий void procedure2() { Выполнение операций procedureZ. ... TaskRunner::run(): Проверка всех событий void proceduresО { Выполнение операций procedures. ... TaskRunner::run(): Проверка всех событий int mainO { srand(time(0)): Раскрутка генератора случайных чисел Button bl( Button 1 ). Ь2( Button 2 ). Ь3( Button 3 ): CheckButton cbl(bl). cb2(b2). cb3(b3): TaskRunner::add(cbl); TaskRunner::add(cb2); TaskRunner::add(cb3): cout Control-C to exit endl: while(true) { procedurelO: procedure2() proceduresО } } III:- В этом примере Команды, представленные объектами классом Task, выполняются синглетным объектом TaskRunner. Объект EventSimulator имитирует случайные внешние события: при периодическом вызове fired() результат через случайный промежуток времени изменяется с false на true. Объекты EventSimulator требуются объектам Button для имитации действий пользователя, происходящих с непредсказуемыми интервалами. Класс CheckButton представляет собой реализацию класса Task, которая периодически проверяется всем обычным кодом програм-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |