Событийно управляемая модель программирования ооп

2. Визуальное программирование. Событийно-управляемое программирование

В концепцию объектно-ориентированного подхода хорошо вписывается способ создания программ, называемый визуальным программированием. Его суть заключается в том, что любой визуальный, т. е. видимый, элемент программы представляет собой объект со своими свойствами и методами. Как правило, все визуальные элементы в VBA являются элементами диалога и размещаются на специальной форме. Разработчику нет необходимости создавать новый объект программно – достаточно просто перетащить его с панели элементов на рабочую форму и задать его свойства в соответствующем окне среды разработки, при этом также сохраняется возможность изменять свойства объекта в коде своей программы. Такой способ создания программ делает создание их интерфейса простым и наглядным.

Visual Basic for Applications не является каноническим объектно-ориентированным языком, таким как, например, С++, во многом он не соответствует понятию классического объектного языка. В литературе его называют событийным (Event-Driven) языком программирования, ориентированным на работу с объектами. Рассмотрим основные особенности VBA.

В событийном программировании вводят такое понятие, как событие. Чаще всего события вызываются пользователем, но могут быть вызваны также приложением, другой программой и т.д. У объекта в событийном программировании наряду со свойствами и методами появляется новая характеристика – набор событий, на которые он может реагировать. Этот набор для данного объекта неизменяем, однако то, каким именно образом будет происходить эта реакция, зависит от программиста. Именно он должен написать процедуру-ответ на событие. Такая процедура называется обработчиком события.

Приведем пример. При нажатии на какую-то кнопку с названием CommandButton1 формы мы вызываем для нее событие OnClick. Для того чтобы описать ответ на это событие, программист должен создать процедуру обработки события (обработчик). Эта процедура будет выполняться каждый раз при нажатии на кнопку.

Читайте также:  Convoy s11 программирование режимов

Кроме того, Visual basic for Applications имеет еще одну особенность –особую форму наследования, реализованную в этом языке, называемую встраиванием. При встраивании объект-потомок включает в себя родительский объект в качестве свойства, т. е. как бы “встраивает” его в себя. Таким образом, доступ ко всем свойствам и методам родителя в объекте-потомке осуществляется опосредованно, через обращение к свойству-родителю.

Все классы в Visual Basic for Applications являются потомками одного единственного базового класса – Object. Это позволяет использовать общий для всех объектных переменных тип, который так и называется – Objeсt. Переменной такого типа может быть присвоена ссылка на любой объект VBA.

Еще одно важное замечание: VBA нам позволяет работать с объектами только через ссылки. Вообще говоря, ссылка – это указатель на то место в памяти программы, где хранится объект. Так как любой объект однозначно определяется по своему месту жительства, то ссылка для объектов – это аналог имени для обычной переменной. Разница заключается лишь в способе присваивания значений: для этого используются две различные инструкции – Let и Set (об этом см. ниже).

Обращение к свойствам и методам объекта в языке VBA имеет следующий синтаксис: Объект.Свойство илиОбъект.Метод

Часто бывает так, что свойство объекта само является объектом и имеет свои свойства и методы. В таком случае для обращения к этим свойствам и методам выстраивается иерархическая цепочка: Объект.Свойство1.Свойство2 … и так далее.

Например, для установки размера шрифта выделенной ячейки таблицы MSExcel используется следующая конструкция:Selection.Font.Size = 20, где selection – это объект (выделенная ячейка), Font – ее свойство – шрифт, а Size – свойство этого шрифта – размер. Следует отметить, что тип присваиваемого значения должен быть тот же, что и тип свойства, в данном случае этот тип – целое число (подробнее о типах переменных будет рассказано ниже).

В VBAопределены так называемые глобальные объекты. При вызове таких объектов можно не указывать имя родителя в иерархической цепочке. Например, предыдущее выражение присваивания будет равнозначно следующему:Application.Selection.Font.Size = 20 из-за того, что объектApplication является глобальным.

Источник

Многоуровневая модель обработки событий

Событие в объектно-ориентированное программировании (ООП) — это сообщение, которое возникает в различных точках исполняемого кода при выполнении определённых условий. Данные сообщения направляются обработчикам (слушателям), что позволяет своевременно реагировать на изменившееся состояние системы.

Большой популярностью пользуется событийно-ориентированное программирование. Эта парадигма программирования говорит, что выполнение программы определяется событиями — действиями пользователя (клавиатура, мышь), сообщениями других программ и потоков, событиями операционной системы и т.д.
Преимущества и сферы применения событийной модели чрезвычайно широки:

  • при связывании объектов событиями, объектам нет необходимости «знать» друг о друге;
  • данный механизм четко вписывается в концепцию ООП;
  • данный механизм позволяет легко реализовывать пользовательские интерфейсы, где каждое действие пользователя – событие, достаточно «навесить» на эти события обработчики;
  • при реализации серверных приложений событийная модель позволяет избавиться от порождения множества обслуживающих процессов;
  • событийная модель также часто используется при программировании игр, в которых осуществляется управление множеством объектов.

Существуют шаблоны проектирования, так или иначе связанные с обработкой событий: Наблюдатель, Команда, Цепочка обязанностей и многие другие. Данные шаблоны используются во многих моделях обработки событий. Однако различные реализации событийной модели накладывают ряд ограничений на возможности разработки программ:

  • при обработке события нельзя выделить главный обработчик, все обработчики равны между собой;
  • при обработке события обработчики ничего не знают друг о друге и о сложившейся ситуации, что не позволяет программисту полностью реализовать задуманный функционал;
  • приходится дописывать дополнительный функционал, если требуется выбрать результирующий обработчик.

Перечень перечисленных ограничений не является полным, однако указанные ограничения являются наиболее существенными. В данной статье предлагается реализация более сложной событийной модели, которая позволит снять все перечисленные ограничения.
При разработке программного обеспечения с использованием данной модели обработки событий последовательность этапов обработки следующая:

  1. Необходимые слушатели подключаются на обработку своих событий.
  2. В программном коде инициируется событие.
  3. Выполняется «первый круг» обработки, всем слушателям подключившимся на обработку данного события предоставляется время на первичную обработку, в процессе которой каждый слушатель может получить собственные данные, данные от инициатора события, а также установить какие-либо данные для передачи во «второй круг» и подать заявку на обработку события во «втором круге».
  4. Среди всех слушателей данного события выбирается слушатель, который подал заявку с наибольшим приоритетом обработки, именно ему предоставляется право на обработку события во «втором круге». В процессе данной обработки он может получить данные от инициатора, собственные данные, данные от собственного обработчика «первого круга». После завершения обработки он может вернуть данные непосредственно инициатору события.

Рассмотрим преимущества данной модели:

  • Возможно «навешивать» один и тот же обработчик на разные события или даже на одно и тоже, но с разными собственными данными.
  • Возможно обрабатывать наиболее широкий круг событий. Например, добавление нового пользователя, вывод дизайна страницы сайта и т.д. В данном случаи событие добавления нового пользователя можно обработать используя лишь «первый круг», а событие вывода дизайна страницы сайта необходимо обрабатывать в «два круга».
  • Выполняется лишь один обработчик «второго круга» (Рассмотрим событие вывода дизайна сайта: на первом круге обработчики анализируя состояние системы выдвигают приоритеты обработки события и лишь на «втором круге» один из них генерирует дизайн страницы сайта).

На картинке представлена схема реализации данной модели. Эта реализация изначально опирается на работу с использованием цепочки вызовов. Ниже представлен пример реализации модели на языке PHP.

  • Events – основной класс. Лишь его объект пользователь может создать сам. Данный класс предоставляет возможность инициировать события и «навешивать» обработчики событий.
    • newListener – позволяет добавить нового слушателя и тут же «настроить» его (добавление происходит через адаптер для Events_Listener – Events_Listener_adapterSET).
    • newEvent – позволяет сконфигурировать новое событие, а затем инициировать его (данное действие происходит через адаптер для Events_Fire – Events_Fire_adapterSET).

    К процессу работы прозрачно для пользователя подключаются и другие классы:

    • Events_Fire – предоставляет общий интерфейс работы с событием, который ограничивают адаптеры;
    • Events_Fire1 – при вызове первого круга обработки. Данный класс позволяет получить все имеющиеся данные текущего состояния, добавить обработчик второго круга, а также установить его приоритет (через адаптер Events_Fire2_adapterSET);
    • Events_Fire2 – при вызове результрующего обработчика («второй круг»). Этот класс позволяет получить все имеющиеся данные, включая данные от обработчика «первого круга»;
    • Events_Listener — предоставляет общий интерфейс работы с обработчиком события. Методы данного класса также используют адаптеры Events_Fire1, Events_Fire2;
    • Events_Data – класс для хранения и передачи данных внутри событийной модели.

Рассмотрим пример работы данной модели:

class SampleListener < public function Fire1(Event_fire1 $EF1) < $EF1->setFinal(Array($this,”Fire2”), $EF1->getListenerData()->sort); > public function Fire2(Event_fire2 $EF2) < return ($EF2->getListenerData()->sort() + $EF2->getFireData()->sort()); > > $listener = new SampleListener(); $data1 = new Events_Data(); $data1->sort = 10; Events::newListener("sampleModul", "sampleEvent", Array($listener, 'Fire1'))->setData($data1); $data2 = new Events_Data(); $data2->sort = 20; Events::newListener("sampleModul", "sampleEvent", Array($listener, 'Fire1'))->setData($data2); $data3 = new Events_Data(); $data3->sort = 30; Echo Events::newEvent("sampleModul", "sampleEvent")->setData($data3)->fire();

После инициализации события sampleEvent вызовется метод Fire1 слушателя $listener с первыми данными (sort=10, именно этот приоритет он и поставит на финальную обработку), а затем этот же метод вызовется с другими данными (sort=20, 20>10, следовательно слушатель с этими данными и получит право финальной обработки события). В заключении вызовется метод Fire2 (Обработчик тот же, но данные $data2). Данные от события (sort=30) складываются с данными от слушателя (sort=20). В итоге событие в ответ вернет нам число 50, которое и будет выведено на экран.

Данный пример показывает, что один и тот же обработчик может по разному реагировать на событие в зависимости от данных слушателя. Также он демонстрирует процесс обработки события, включая результирующий, единственный вызов Fire2 (Представьте что именно в этом методе, например, генерируется дизайн страницы сайта, а данные – это внешний контекст обработки события).

Реализовав данную модель обработки событий удалось снять все указанные выше ограничения. В настоящее время модель ориентирована на конкретный продукт (имеются паразитивные методы необходимые только в этом продукте), но если будет интерес, то можно подготовить код к публичной версии.

Также можно реализовать данную модель и на других языках программирования. В cpp можно в качестве данных передавать указатель, а в методах обработки использовать reinterpret_cast или воспользоваться шаблонами.

Реализация в каждой конкретной ситуации может немного отличаться, однако основной смысл именно в реализации двух или более уровней.

Источник

Оцените статью