![]() |
запуск событий одного класса во множестве
Не знаю как правильно назвать тему, извиняйте.
Давно мучает такой вопрос, есть у нас класс управляющий сервером, тоесть класс приемник данных от сервера и соотв диспатчит события при приходе определенных данных. Задача - подписываться на события из разных классов. Самый простой вариант делаем класс статическим, создавая внутри диспатчер, и теперь из любой точки можно подписаться как Код AS3:
Вариант два, так же статик, но передавать туда диспатчер типа Код AS3:
Но вариант 1, тоже не блещет, где то говорилось и обсуждалось , что статик в этом случае не есть тру. Так вот интересно ваше мнение, 1. имеет право на жизнь статик в данном контексте ? 2. если не статик, то как ? Архитектруа Код AS3:
|
написать класс, в котором будет единственная функция, она будет диспатчить события, а все остальные ваши классы наследуйте от написанного класса. Я бы так сделал, на мой взгляд данный вариант более логичен нежели вариант со статикой
ServerDispatcher.as Код AS3:
Код AS3:
Код AS3:
|
|
Та даже если уж в сторону статика смотреть то лучше синглтон крутить.
А так да, обсервер имхо лучший вариант. Хотя от синглтона мало отличаться будет в данном контексте. Но обсервер можно будет сделать не только для сервера а и вообще для рассылки чего-попало кому-попало. Тоже некая гибкость, хотя и контроллить сложно. С обсервером получится асинхронная структура, с недостаточностью опыта может оказаться фатальным. |
Цитата:
Код AS3:
|
Ахах) Ну ужас весь от интерфейсов, которые необходимы только потому, что в классической схеме не используются события, а идет прямое оповещение (просто вызов интерфейсного метода у подписчиков).
Цитата:
Код AS3:
|
Что-то ничего не ясно. EventDispatcher и есть Observer.
|
Цитата:
|
Цитата:
Или в блоге каком-то, не помню. И уже не первый раз тебе отвечают, что диспатчер это просто одна из частных реализаций обсервера. Но отнюдь не сферический обсервер в вакууме. |
Wolsh спасибо я тебя понял.
|
Цитата:
|
Цитата:
|
Эмм... Мне одному кажется, что EventDispatcher - это нотифаер (IObservable)?
|
Цитата:
|
В классическом обсервере нет ни событий, ни их типов соответственно. Все подписчики уведомляются без разбора при любом изменении нотифаера. Вызывается один и тот же метод у всех. Метод описан в интерфейсе, и все подписчики должны его реализовывать (одно из отличий от EventDispatcher, где регистрируются методы и вместо неприменимых здесь интерфейсов соблюдается "устная" договоренность о сигнатуре). Реализация соответственно разная, каждый запрашивает то что ему интересно. В этом избыточность – допустим подписчика интересует только изменение ширины, но он будет получать уведомление при всех изменениях: текста, высоты, цвета. Потом сделает запрос нотифаеру и узнает, что ширина таки не изменилась – ложная тревога.
На эту схему конечно можно нагородить и объекты данных типа событий, описать это в интерфейсе.. И желаемый тип изменений можно пририсовать в регистрацию, чтобы не гонять пустое.. Но базовое отличие от EventDispatcher именно в том, что регистрируются не методы а экземпляры, и соответственно требуется интерфейс подписчика, гарантирующий наличие метода для получения уведомлений. |
Как-бы никто не спорит что реализации у него разные и классический сильно отличается от EventDispatcher, вопрос в том - зачем оно нам нужно.
Если вернуться к вопросу топика и перефразировать его в 2-х словах: "Есть класс, дающий данные с сервера и он диспетчит события об их получении. Хочу отовсюду на них подписываться" Тут обычно произносится фраза, за которую часто хочется ударить томиком "совершенный код" по рукам: "А давайте сделаем этот класс синглтоном" (имеется в виду сам провайдер данных им сделать). Но, на самом деле, можно и сделать - вряд ли вы так уж серьезно огребёте проблем с общедоступным провайдером данных. А можно и не делать - передавать провайдеры кому надо просто. А статическим класс делать - как-бы нет причин, ну не замучаетесь Вы с написанием instance - провайдер данных - это не коллекция математических функций - к нему так часто не обращаются. А вот с проблем с невозможностью наследования, тестированием, а так же если второй экземпляр потребуется, или общий интерфейс для 2-х разных провайдеров - огребёте. 2 in4core: Или я чего-то не понял и кроме "подписаться отовсюду" есть ещё какие-то проблемы? |
Не вижу ничего страшного в синглтоне.
У меня в одном маленьком проекте (в большоих пока не пробовал такого) следующая схема: Есть некий коннектор сервера - его дазача принимать и отправлять сообщения плюс конвертировать их в читабельный для флешки вормат. Есть контроллер сервера который знает что делать с каждым сообщением, он там уже парсит и меняет модель. А вот фишка вся в этой схеме в том что модель - синглтон:) Такое себе здаравенное дерево данных со своей структурой классов. Есть пачка контроллеров, есть пачка вьюх. Когда контроллер инициализируется он вьюхи которыми рулит подписывает на какую-то из веток модели. И дальше всё типа вуаля. Ну синглтоном мою модель назвать наверное неверно, так как модель действительно одна но к корневой модели доступ есть буквально у нескольких классов, куда-то глубже уже только ветки передаются. Тоже как вариант. Вообще идея оповещать какую-то кнопку что пришли данные с сервера слегка логически неверно как по мне. Эта кнопка о существовании сервера не должна догадываться, она должна видеть свою модель и просто отображать то что в ней. И данную дискуссию как в в плане "посидим, поговорим" - да, но делать я бы так не стал. Ну может и стал бы, но постарался бы избежать. |
Код AS3:
Я имел счастье наблюдать 3 синглтона ссылающихся друг на друга (не считая кучи других, на которые они ссылались и которые ссылались на их) - там без поллитры было не разобраться кто кого дергает и когда кто инициализируется. А покрыть хотя бы один Unit-тестом - несбыточные мечтания. Хотя, если их мало - и сами синглтоны и классы, которые их используют вполне покрываются тестами, а те же "не синлтоны", ссылающиеся на половину приложения покрыть практически невозможно. Цитата:
Цитата:
Цитата:
- контроллер получает данные с сервера (когда ему другой контроллер скажет или какую-нть кнопку нажмут или еще по каким условиям) - контроллер применяет полученные данные к модели - а все остальные работают с моделью и слушают её. Но может для задачи in4core это перебор и он решил интегрировать получение данных с сервера в модель - кто знает, тема топика вроде не про это. |
Это всего лишь инструмент. Но бывает кто-то рубит деревья бензопилой и пилит топором, чего уж.
Добавлено через 19 минут Цитата:
Мейн раздал всем кому позволено видеть ссылку на корень(мейнКонтроллер, серверКонтроллер, еще там что-то, не помню, но в общем объектов пять не больше). Далее мейнКонтроллер уже раздает ссылки на ветки модели всем дочерним. А насчет для друга для себя - это всё уже внутри этой большой модели. Например большая модель, в ней: - модель для статических данных с сервера - модель для профиля друга - модель для текущей игры - прочее блаблабла. Сама идея возникла именно из-за коммуникации с сервером. Контроллер сервера меняет модель и мы обходимся безо всяких обсерверов и прочей сомнительного качества лабуды и промежуточных явлений в виде маленьких контроллеров. Вьюхи сами видят изменения большой модели. |
Цитата:
|
Другим точкам сервер не нужен. Моё мнение такое.
|
Цитата:
Значит, если данные выдавать на полях провайдера - нужно его самого передавать всем заинтересованным, а там уж пусть подписываются и читают. (сам ли провайдер работает с сервером, или он просто модель, которую меняет класс, работающий с сервером - это другой вопрос, т.е. по логике не обязательно класс для работы с сервером тягать - лучше тягать только модель, которую он меняет) Т.е.: создал вюшку "морковь". Ты же ее не из ничего создал - была модель, которую создал контроллер, когда получил данные от сервера. Скорее всего была главная вюшка, которая услышала собырие ADDED_ITEM(с полем "модель моркови"), которая создала вьюшку МОРКОВЬ, куда передала при создании модель моркови. И в следующий раз, когда сервер пришлет изменение степени зрелости этой моркови - контроллер найдет по айдишнику модель моркови в главной модели и поменяет параметр "зрелость", продиспетчится событие, которое услышит вьюшка и которая отобразит изменения. Т.е. вьюшка получила модель(провайдер изменений и данных) в момент создания. При этом контроллер серверный ничего и не знал о вьюшке. Если данные об _изменении_ передавать в событии - есть некоторые проблемы - если вьюшка появилась после загрузки данных - она их не получит, поэтому этот случай не рассматриваю. Или именно так у тебя дела и обстоят? |
Передавать детям.
Добавлено через 4 минуты Мне вообще непонятно о чем речь. Один большой класс, который работает с серваком и хранит все полученные данные и раздает их по запросу, посылая перед этим событие апдейта данных? Бррр. |
Цитата:
|
Цитата:
Но вообще да, тема куда-то уходит и начинает дублировать статью про "правильный MVC" |
На самом деле мне интересно тоже кто как взаимодействие с сервером организовывает?
Как выглядит одно сообщение? Как оно обрабатывается клиентом? Кем оно обрабатывается? Что делать дальше с полученной от сервера информацией? И в таком духе. Делитесь своими изобретениями и догадками. Я про свое рассказал. - Есть коннектор - внутри сокет-сервер, хттп-сервер, конфиги обрабатывает, может работать с разного рода серверами и выдавать не зависимо от этого сообщения в едином формате. Может принимать джейсон, может принимать АМФ, сейчас вот протобуф тестирую. Это всё здесь. - Есть ДатаКонтроллер - получает отформатированное сообщение от коннектора, смотрит что пришло. Ну и ему глобально пофиг что там и с кем общается коннектор. Урлов он не знает, портов тоже, даже по какому протолу общение происходит тоже не вкурсе, ему пофигу хттп или сокет. Его задача только отправлять и получать сообщения во внутреннем формате в коннектор. Коннектор там разберется уже. - А дальше в разных проектах по разному. В одном проекте вот как я выше написал - одна большая модель, которая подключена к ДатаКонтроллеру, датаКонтроллер напрямую меняет модель при получении сообщения. На ветки этой модели подписаны вьюшки, вьюшки не курсе о существовании большой модели, видят только свои маленькие которые внутри этой большой. В другом проекте есть обсервер, датаКонтроллер получает сообщение, спамит обсерверу оповещение мол так и так такие то данные изменились. Сами данные записывает в синглтон БД игры. К этому синглтону имеют доступ все кому не лень. Как-то так. А как это выглядит у вас? |
ЧТобы не быть голословным вот более понятная архитектура , чтобы ясно было о чем речь ВСЕМ.
Код AS3:
Тоесть вот таких onSomeBack(vars:*) или callSomeMethod очень много соотв. Тоесть получили мы определенную пачку данных продиспатчили об этом нужным евентом. Почему встает такой вопрос, ну допустим : 1. Main тут мы создали и подключаемся, если подключение к серверу не прошло, просто не грузим библиотеки кликента и графику... ну нет смысла например ) 2. Если соединение прошло, открываем некий ClassFrameWork где подписываемся на сообщения типа ( если это игра ) игра началась, игра закончилась и т.п. 3. Внутри же ClassFrameWork создается некий класс GameFrameWork где уже подписываемся на конкретные события игры - типа перс появился, перс умер и т.п. П.с. конечно эти 3 пункта набросаны от башки и никто иак не делает, но я просто доношу смысл |
Цитата:
Есть класс BaseOperation обертка над урллоадером со всеми обработчиками. В качестве параметра принимает урл, и два колбека (для результата и для ошибки). Шлет запрос, принимает ответ, если все хорошо - отдает в результатколбек ответ (хмл и джейсон) , плохо - ошибку в ошибкуколбек :о). Если совсем плохо (невалидный хмл) падает :о)), но в отлаженном проекте такого нет. Ну и дальше расширяющих классов пачка. Для каждого запроса. GetUserListOperation EditUserOperation CreateProjectOperation Каждый принимает как минимум два колбека + дополнительные парметры. В ответ отдает десериализированный объект или массив объектов. То есть в любой точке программы, могу получить нужную инфу от сервера. Если надо, то каждая операция может в статике кешить результаты и по запросу отдавать кеш. Короче мне нравится и удобно. |
2 in4core:
Насколько понял, статический класс, который ты привел в качестве примера - это не "провайдер данных", как я думал, а просто класс, реализующий запросы к серверу. Если отбросить инициализацию, забыть что класс статический и загнать диспетчер внутрь (вроде нет смысла передавать его снаружи) интерфейс бы выглядел так: Код AS3:
Можно еще раз объяснить "что не нравится" (просто я могу много чего рассказать, что мне не нравится в вашем примере со статикой, но это будет долго, а главное будет очень зависеть от контекста)? Всмысле вот есть этот статический класс, что там мешает на него подписываться, или тебя раздражает, что он статический, или если бы он был не статический у тебя возникают другие проблемы, короче хочется услышать то же, что и в первом посте, только конкретнее. |
Цитата:
Да раздражает фича Static.addEventListener , хотелось бы из любого места _dynamicClass.addEventListener |
Если только это раздражает - сделай класс нестатическим и передавай всем кому надо
если тяжело передавать - сделай синглтоном. Вроде здесь проблем быть не может. Вообще синглтон всегда гибше статик-класса - с ним можно больше вещей сделать. Просто у него чуть выше "overhead", т.е. Math.instance.cos(a) смотрелось бы дико (да и обращение бы дольше выполнялось). А здесь то: Код AS3:
Даже с тестами все в разы проще, чем со статиком, пример подмены класса на фейковый: Код AS3:
Код AS3:
|
Синглтон не люблю за констуркцию Class.getInstance() - меня это злит
|
Дык присвой полю это Class.getInstance() - чтобы код класса не засоряло.
А вообще, если тебя не злит: - невозможность наследования; - невозможность передать в качестве параметра; - проблемы с тестированием; - затрудненная инициализация класса (хотя с синглтонами не намного лучше); используй статики на здоровье. Как-бы я знаю только такие способы обеспечения доступа к объекту: - сделать публичный статический метод/поле, возвращающий объект (синглтон сюда тоже относится) - передавать объект в конструктор - передавать объект в метод - передавать объект в поле - сделать сам класс публичным статическим (никаких объектов!) - использовать IoC контейнер для автоматической передачи через конструктор/метод/поле - создать событие "ДАЙТЕ МНЕ ПРОВАЙДЕР", сохранить в событии ссылку на клиента провайдера, послать баблингом вверх по цепочке, где-то вверху поймать, узнать клиента, присвоить полю клиента этот провайдер. Теперь у клиента есть ссылка на провайдер, хотя он понятия не имел где тот находится - ура :) Ну что-то же из этого должно нравиться!? |
expl выше по коду вариант нормальный. учту
|
| Часовой пояс GMT +4, время: 18:26. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.