Russian Qt Forum
Май 06, 2024, 22:02 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 3 [4] 5   Вниз
  Печать  
Автор Тема: Вопрос по архитектуре приложения. Медиатор  (Прочитано 34397 раз)
DmitryM
Гость
« Ответ #45 : Июнь 08, 2012, 13:59 »

Пример с задачей наверное всё-таки не самый удачный, т.к. подразумевает рекурсию. Если все кнопки подключены к одному и тому же событию, плюс зациклены, то и получим в итоге круговорот. В коде пришлось ввести отдельную функцию autoClick(), чтобы избежать этой неприятности.

Как видно, медиатор при решении данной задачи не очень-то эффективен. Проще на сигналах, да или в лоб, как описывалось выше, через ссылки. Нужен другой пример.
Если click() вызывается в момент нажатия на кнопку,  и autoClick() переименовать в someButtonСlickEvent().
То все кнопки получат сообщения о том, что на какую то из них нажали, и могут обработать эту ситуацию.
И тут уже медиатор вполне пригоден.
Записан
alexis031182
Гость
« Ответ #46 : Июнь 08, 2012, 14:14 »

Имеется ввиду отправка медиатором кастомного события someButtonСlickEvent()? Да, конечно, тогда цикличности не будет.

Но всё равно остаётся открытым вопрос, какие плюшки в примере "Медиатор с кнопками" мы получаем в сравнении с традиционным подходом использования перекрёстных ссылок (не говоря уже о сигналах даже)?
Записан
DmitryM
Гость
« Ответ #47 : Июнь 08, 2012, 14:39 »

Но всё равно остаётся открытым вопрос, какие плюшки в примере "Медиатор с кнопками" мы получаем в сравнении с традиционным подходом использования перекрёстных ссылок (не говоря уже о сигналах даже)?
повторюсь медиатр призван решить следующую проблему
Цитировать
Обеспечить взаимодействие множества обьектов, сформировав при этом слабую связанность и избавив объекты от необходимости явно ссылаться друг на друга.
Мы не используем перекрестные ссылки. У нас кнопки ничего не знают друг о друге.
Когда мы вынесем someButtonСlickEvent() в базовый класс Коллеги, то кто угодно унаследованный от это класса будет получать сообщение о изменение состояния кнопки.
И не менее приятное, у нас может быть произвольное количество коллег.
Записан
alexis031182
Гость
« Ответ #48 : Июнь 08, 2012, 14:56 »

Хм... тогда получается использование медиатора в примере с кнопками обосновано. Это как некий задел на будущее с соблюдением принципов ООП.

Предварительное "Итого". Конечно логику примера с кнопками имеет смысл реализовывать на перекрёстных ссылках, если не планируется никакого расширения. Скажем, есть две-три кнопки, а ну и ладно, сойдёт, зажарится как-нибудь. Но если понадобится добавить изыска (ещё пару тройку других типов виджетов), то медиатор безусловно пригодится. Вывод верен?
Записан
DmitryM
Гость
« Ответ #49 : Июнь 08, 2012, 15:13 »

Но если понадобится добавить изыска (ещё пару тройку других типов виджетов), то медиатор безусловно пригодится. Вывод верен?
Если брать Madiator (GoF), то там пример строится как раз на виджетах.
Не знаю как насчет пары тройки других виджетов, но если пишешь свою библиотеку для работы с виджетами(может пригодиться, если захочешь, что бы было как в FBReader, поддержка интерфейсов на qt3, qt4, gtk+), то скорее всего пригодиться.
Записан
nata267
Гость
« Ответ #50 : Июнь 08, 2012, 16:16 »

Давайте попробуем написать такой медиатор, пусть в псевдокоде. Я лично что-то затрудняюсь "сходу"
Вот тебе example на разных ЯП включая C++.


мой пример имеет много общего, за исключением того, что в моем примере медиатор не выполняет сам никаких действий, а просто является посредником, так даже удобнее, но если внести обработку запросов от коллег медиатору в класс медиатора,
Код:
.....
 virtual void Mediator::Send(std::string message, Colleague *colleague)
        {
                if (colleague==static_cast<Colleague*>(m_Colleague1))
                {
                        m_Colleague2->Notify(message);
                }
                else if (colleague==static_cast<Colleague*>(m_Colleague2))
                {
                        m_Colleague1->Notify(message);
                }
        }
....
то получится как раз тот самый медиатор из данной статьи
« Последнее редактирование: Июнь 08, 2012, 16:28 от nata267 » Записан
DmitryM
Гость
« Ответ #51 : Июнь 08, 2012, 17:09 »

с приведением через static_cast главное на запутаться с направлением иерархии наследования Улыбающийся
Записан
alexis031182
Гость
« Ответ #52 : Июнь 08, 2012, 18:15 »

Сравнение по адресу. Хорошо ли это? Меня терзают не то чтобы смутные, но всё же сомнения, стоит ли это практиковать? Может для классов лучше применять оператор сравнения?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #53 : Июнь 08, 2012, 18:40 »

Если, допустим, изменить задачу таким образом. Пусть существует некоторое кол-во кнопок (Button) и надписей (Label). Нужно при помощи медиатора реализовать логику: если нажали на любую из кнопок, то сменить текст в надписях.
Лады, поехали

1) Считаю сохранение указателя на медиатор в члене класса Button явно неудачным, т.к. это требует наследования (напр от QPushButton). Эта тема частенько мелькает, поэтому чуть подробнее. Добавляемый ф-ционал слишком мал, и наследник становится "ни пришей ни пристегни". Будете ли Вы использовать такого наследника в др проектах - или хотя бы во всех окнах данного? Если да - вперед, обновляйте все имеющиеся окна (или как-то не тянет? Улыбающийся) И заодно поразмыслите что если образовался еще другой "наследник-однодневка".  Если нет - ну жить можно, но как-то несолидно. Другой пример: допустим мы затем решили использовать чекбоксы вместо кнопок, или "кнопки с картинками" (др класс) - куда тогда деваться с нашим наследованием?

2) Простое и хорошее решение - отдаться паренту, пусть он меняет тексты. У него всегда все контролы на руках и он знает что делать. Конечно не напрямую В Qt это просто сигнал, в др системах эта точка управления всегда есть (напр WM_COMMAND в WinAPI).

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

Код
C++ (Qt)
class CAdjuster : public QObject {
Q_OBJECT
 
public:
 void AddPair( QWidget *, QWidget * );
 
public slots:
 void Adjust( QWidget * src, TCommand cmd  );
 
typedef enum {
cmd_SetButton,
cmd_SetLabel,
} TCommand;
 
private:
QVector <QPair<QWidget *, QWidget *> > mData;
};
 
Использование:

- делаем экземпляр CAdjuster членом окна
- после создания кнопка+текст вызываем AddPair
- вяжемся сигналами на слот Adjust

Ну а какой это паттерн - я хз. Здесь много знающих людей сорящих ссылками направо и налево, вот они знают  Улыбающийся
« Последнее редактирование: Июнь 08, 2012, 18:43 от Igors » Записан
alexis031182
Гость
« Ответ #54 : Июнь 08, 2012, 19:09 »

Лады, поехали

1) Считаю сохранение указателя на медиатор в члене класса Button явно неудачным, т.к. это требует наследования (напр от QPushButton). Эта тема частенько мелькает, поэтому чуть подробнее. Добавляемый ф-ционал слишком мал, и наследник становится "ни пришей ни пристегни". Будете ли Вы использовать такого наследника в др проектах - или хотя бы во всех окнах данного? Если да - вперед, обновляйте все имеющиеся окна (или как-то не тянет? Улыбающийся) И заодно поразмыслите что если образовался еще другой "наследник-однодневка".  Если нет - ну жить можно, но как-то несолидно. Другой пример: допустим мы затем решили использовать чекбоксы вместо кнопок, или "кнопки с картинками" (др класс) - куда тогда деваться с нашим наследованием?
Так решение о применении каждого конкретного паттерна должно основываться, исходя из условий задачи. А Вы уже ведёте речь о повсеместном применении. Паттерн медиатора, о котором эта тема, сам по себе не предполагает собственное использование со всеми подряд QPushButton'ами и т.п., но лишь в том случае, когда сгруппированный функционал взаимодействия между объектами классов рационально вынести в посредника. Другими словами, если мы и определили класс-наследник для некоторых QPushButton, то это не значит, что всех подряд надо гнать под одну гребёнку. Я думаю так.
Записан
nata267
Гость
« Ответ #55 : Июнь 08, 2012, 19:55 »

Мне кажется пример с кнопками и метками не совсем жизненный, и в принципе задача довольно простая чтобы с ней заморачиваться. Я предложила данное решение для задачи: Как организовать взаимодействие компонентов сложной системы, не
связывая их напрямую друг с другом. То есть получить систему разбитую на модули но со слабой связностью. Может быть существуют и другие более красивые  решения данной проблемы??
Записан
DmitryM
Гость
« Ответ #56 : Июнь 08, 2012, 20:17 »

И пошел поток бреда:
1) ...
2) ...
3) ...
Чукча видно писатель, а не читатель. Вот оригинальный Mediator GoF.
1.
Система оповещения через посредник достаточно большой функционал.
В зависимости от реализации посредника вызов может произойти моментально, отложено или вообще по rpc вызвать кого та на другой машине.  Ты не возмущаешься наличием нескольких евентов у QObject и кучи евентов у QWidget.
2.
Какой парент? Паренты это паттерн Компоновщик(Composite pattern), который служит для организации иерархии объектов(не классов )
3. А ну ка сделай все это на чистом C++
Записан
nata267
Гость
« Ответ #57 : Июнь 08, 2012, 20:19 »

Зачем окну нужен "Менеджер настроек"? Чем плохо если окно  просто запишет прочитает QSettings?
Для того наверно чтобы все время не создавать объект QSettings для каждого окна, а чтобы делать это централизовано. В менеджере настроек сразу определяется куда будут записываться настройки, а также происходит инициализация объекта QSettings:
m_settings(qApp->organizationName(), qApp->applicationName())
Кроме того мы сможем менять поведение менеджера на специфичесое для данного проекта.
« Последнее редактирование: Июнь 08, 2012, 20:26 от nata267 » Записан
DmitryM
Гость
« Ответ #58 : Июнь 08, 2012, 20:28 »

Мне кажется пример с кнопками и метками не совсем жизненный, и в принципе задача довольно простая чтобы с ней заморачиваться.
Вот тебе другой возможный приме:
У тебя есть физический объект, облупленный кучей датчиков. Ты с подошью обратных вызовов делаешь так, что бы сигнал с датчика обрабатывался соответствующим методом класса. Естественно что состояния этого класса меняется, и тут тебе нужно что бы все , кому нужно следить за этим событием были проинформированы.
Дальше ты можешь писать сколь угодно много обработчиков (классы Коллег).
И вот на базе медиатора получилась событийная модель.
Я предложила данное решение для задачи: Как организовать взаимодействие компонентов сложной системы, не
связывая их напрямую друг с другом. То есть получить систему разбитую на модули но со слабой связностью. Может быть существуют и другие более красивые  решения данной проблемы??
Не совсем то, но всю эту систему можно накрыть другим фасадом(Facade).
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #59 : Июнь 08, 2012, 20:43 »

Не, я бы всё же назвал тему как то так: К вопросу о паттерне Медиатор, или О особенностях использования Медиатора или...
А так название темы совсем не пойми о чём.. В смысле не отражает суть вопроса, имхо(

Наталья, не слушайте Вы никого, кто говорит, что это захламит ваш чердак и потом найти нужную вещь будет нереально.. Это всё бред) Холмс имел в виду совсем другое) Очень хорошо, что вы интересуетесь и изучаете паттерны, ищите, блуждаете.. Всё это во благо) Кто ищет - вынужден блуждать)

ЗЫ
А если кто-то будет наезжать здесь, скажите, что Вы человек Макса))     
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: 1 2 3 [4] 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.078 секунд. Запросов: 22.