Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Организация проекта (алгоритм) (http://www.flasher.ru/forum/showthread.php?t=196739)

filepark 29.03.2013 06:31

Организация проекта (алгоритм)
 
Вопрос по организации проекта, неверняка я изобретаю велосипед, поэтому просьба наставить на путь истенный.

Суть идеи:
Проект состоит из двух основных типов объектов - "менеджеры" и "холдеры", помимо основного класса, конечно есть и другие, но это не принципиально. Менеджеры реагируют на события, обрабатывают их и сообщают об изменении своего состояния, сами ничего не отображают. Холдеры решений не принимают - это только контейнеры отбражаемых объектов, ловят сообщения менеджеров об изменениях и отбражают то, что им положено в данном состоянии.
Напрямую объекты неимеют никаких связей, только менеджеры имеют публичные свойства, чтобы можно было определить их состояние в данный момент. Ни один холдер не имеет связи с другим холдером - табу. Никто не может сказать менеджеру изменить состояние, только он сам на основе приходящих эвентов.

Как это работает:
Когда что-то происходит в менеджере или холдере он шлёт соотв. эвент, основной класс его ловит и рассылает его всем менеджерам и холдерам.
Заинтересованные объекты его обрабатывают и шлют свои эвенты, и так далее, Т.е. по сути работа программы это только обмен событиями через объект основного класса. Т.о. большинство основных элементов даже не подозревают о существовании других объектов - им приходит эвент, а кто его послал и из-за чего их не касается.

Пример:
ScreenManager - отвечает за состояния отображения всех объектов. ButtonManager - состояния всех кнопок. MenuHolder - отображаемых объект, в нём находится кнопка фулскрин.
Пользователь кликает кнопку фулскрин в MenuHolder, кнопка шлёт эвент "кнопка фулскрин кликнута", сообщение ловит объект основного класса и рассылает его всем менеджерам и холдерам.
Заинтересован только ScreenManager, остальные не реагируют. ScreenManager в ответ на это событие переводит плеер в полноэкранный режим и шлёт событие "ScreenManager изменил состояние на фулскрин" Его ловил основной объект, рассылает его всем менеджерам и холдерам.
Но в нём заинтересован только ButtonManager, он решает кнопка фулскрин переходит в нажатое состояние и шлёт эвент "кнопка фулскрин нажатое состояние". Основной класс опять рассылает его всем. При этом ButtonManager понятия не имеет есть ли вообще кнопки фулскрин и сколько их и где они.
Но этот эвент доходит до MenuHolder и он циклом по массиву кнопок сообщает всем им, что кнопка фулскрин нажата, ведь даже MenuHolder не знает какие именно кнопки он содержит.
Кнопка фулскрин ловит это событие и нажимается!

maxkar 29.03.2013 11:16

А в чем вопрос? Да, есть очень похожее решение. Называется message bus. Отличается от вашего только тем, как именно отправляет начальное сообщение компонент. В классическом варианте компонент имеет ссылку на шину (bus) и прямо в нее отправляет сообщение (а не отправляет событие наверх). Это обычно проще (не нужно поддержку EventDispatcher реализовывать).

Для клиентских приложений (flash, desktop application) тоже может быть применимо.

А вот в вашем примере я бы не ButtonManager к шине прикручивал, а сами кнопки. Т.е. ButtonManager так же отправляет событие "fullscreenButtonPressed" и уже сама кнопка получает и обрабатывает событие. При чем там menu holder? Наверное, концептуально правильнее было бы даже так: Кнопка "фуллскрин" отправляет событие "request fullscreen". Screen manager получает и обрабатывает событие, отправляет новое - "set fullscreen mode". Его получает кнопка fullscreen (среди других обработчиков) и меняет свое состояние. Или менять взаимодействие между button manager и кнопками напрямую (хранить в button manager нужные ссылки).

filepark 29.03.2013 11:40

Спасибо за наводку, поищу информацию о message bus, для этого я и писал.

А на счёт вашего комментария, где "концептуально правильнее так", не согласен. Весь смысл в том что каждый принимает решения на своём уровне и не касается чужих дел. ScreenManager - управляет экраном, кнопки его не интересуют, Кнопка не может принимать решение нажаться ей или нет, ей думать неположено, она не знает о экранных режимах, она не знает зачем она нужна, у неё есть только имя. ButtonManager может её нажать или вообще отключить, и не конкретную кнопку, а кнопку с определёнными параметрами, потому что он не знает какие кнопки есть. MenuHolder нужен чтобы принимать сообщения от главного объекта, и спускать ниже - гланый объект не знает, что есть какие-то кнопки, они зарегистрированы в холдерах.
Смысл такого построения, насколько это возможно, изолировать объекты друг от друга. Тогда программа будет как мозаика, можно дабавить или убавить объекты, другие этого не заметят. Напимер, добавление новой кнопки в MenuHolder сведётся лишь к её добавлению в массив кнопок.

maxkar 29.03.2013 12:46

Цитата:

MenuHolder нужен чтобы принимать сообщения от главного объекта, и спускать ниже - гланый объект не знает, что есть какие-то кнопки, они зарегистрированы в холдерах.
Это можно решить как раз глобальной (общей) шиной сообщений. Т.е. все кнопки зарегистрированы в ней. Кнопки все равно знают свой id (события то отправляют да и им доставляют сообщения по этому id) и могут реагировать на сообщения, специально отправленные для "кнопки с указанным id". Причем сообщения будут именно уровня кнопок (set enabled/set disabled). Примерно то же, что вы предлагаете, только механизм доставки не "по дереву", а через общую шину.

Или можно оставить и как у вас - "локальную" шину для меню, при этом транслировать сообщения из "глобальной" шины в "локальную". Подход удобен для объектов с различным временем жизни. Например, для какого-то диалога временно подписать его на шину, а потом отписать.

Мои замечания касаются даже не столько идеологии (там все нормально), а технической реализации. Чтобы не писать отдельно "диспетчеризацию" для MenuHolder, подобную же диспетчеризацию - для диалогов и т.п. А чтобы можно было взять "message bus" и "message bus translator", например, и использовать везде их. В общем, на это все нужно в коде смотреть.


Часовой пояс GMT +4, время: 05:32.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.