![]() |
:) Шкаф "при чем" в случае влажности, он таки предохраняет книгу, и может даже иметь влагозащитные свойства, корректирующие влажность внутри. Если уж в программе реализована система влажности, влияющая на параметры объектов. Согласен, конечно, пример не самый наглядный. Но и в программе, особенно на стадии проектирования, не все отношения так наглядны, как в армии. Потому и надо абстрагироваться и искать общий принцип, и потом уже подчинять ему детали реализации.
|
Код AS3:
Цитата:
Речь пойдёт о вьювере (представлении в терминологии MVC), который должен нарисовать модель - сегмент игры, содержащий данные и игровую логику. Допусти пользователь куда то тыкнул и вылезло окошко. Модель генерит событие (но щас речь не об этом) и вьювер должен как то это окно нарисовать. Есть суперкласс view, в котором помимо прочего есть класс GUI, в котором есть класс window, в котором, в свою очередь есть класс AttackConfirmDialog, у которого есть метод Show. Заметьте - эта цепочка может иметь сколь угодное количество звеньев. Если следовать вашей логике, в ответ на изменение модели, я должен буду сделать что-то типа view.GUI.window.attackConfirmDialog.show() Но это утопия. По скольку диалогов может быть сотня, а событий, которые генерит модель, крича о том, что она изменилась и того больше. И тогда класс view у меня превращается в класс-бога, который должен знать всё и про всех. Пользователь подвинул мышь - view.GUI.cursor.setPos(), нажал меню - view.GUI.window.saveMenuDialog.show() и т.п. Вот это и есть смерть ООП. Я поступил следующим образом - реализовал в представлении (вьювере )диспетчер сообщений и поместил его экземпляр в класс view. Теперь, когда модель говорит, что надо нарисовать окошко или контроллер говорит, что пользователь подвинул мышь, ядро движка обращается к диспетчеру сообщений view и тот уже генерит событие типа ON_WINDOW_SHOW или ON_MOUSE_MOVE, на которое подписаны соответственно классы window и cursor. Всё элегантно и просто. И незачем порождать цепочку вызовов. Корневому классу view незачем знать, что где-то есть метод диалога show и уж тем более незачем знать, какого из сотни диалогов именно. Максимум, что он может знать - это то, что можно дать команду GUI нарисовать окно, а тот уже сам разберётся. Но в моём случае, с диспетчером сообщений и это не обязательно. |
Цитата:
У меня страницы книги листала книга, а не город, в котором дом, в котором комната, в которой шкаф, в котором книга. Никогда не думал, что в MVC место отображения курсора или даже диалоговое окно как-то зависит от модели. Мне всегда казалось, что с этим прекрасно справляется вью, а модель интересует разве что результат выбора пользователя. Но я не эксперт в MVC. Да и традиционный холивар о том, кто как готовит MVC меня сейчас совсем не интересует. Жаль только, что не удается донести до Вас мысль о прелестях иерархии и разделения ответственности. |
Цитата:
Например военный советник предупреждает о нападении. Но речь вовсе не об этом и не о MVC Цитата:
Если внимательно почитать первую страницу, вопрос был в том - как правильно "спускать" переменные вниз. Не хотелось передавать ни кучу аргументов в конструкторы, ни уж тем более ссылку на верхний класс. Добавлено через 13 минут конкретно в моём примере Цитата:
а так же методу view.render.render() следовательно он должен лежать где то наверху, на уровне view. и я его должен как то спустить до уровня view.GUI.window.attackConfirmDialog.show() но он (битмапдата) нафиг не нужен не GUI, не window, не кучи других классов. Вот как быть? Добавлено через 31 минуту т.е. у меня либо ошибка проектирования архитектуры, и класс attackConfirmDialog не должен знать о переменной верхнего уровня BitmapData и следовательно не должен обладать методом Show(). И тогда получается окно не должно само себя рисовать на глобальном холсте, а это должен делать какой то "глобальный" рендер, перебирая все открытые окна и рисуя их. Либо я сдаюсь тогда ) |
Не знаю, как устроен view.render.render(), как он рендерит attackConfirmDialog, не имея на него ссылки, поэтому ответ опять получится расплывчатым.
В целом Вам уже ответили. Если надо спускать сверху вниз, то надо спускать, какую бы нелогичность Вы в этом не увидели. Никто не заставляет промежуточные классы хранить ссылку, достаточно передать ее по цепочке методов. Подчеркиваю: если есть необходимость. Если битмапа нужна только attackConfirmDialog, то логично наверно там ее и хранить. Если она нужна разным производным window, то место ей в window. Да Вы и сами это прекрасно понимаете. Загвоздка в рендере, который видимо не может спросить часть attackConfirmDialog у самого attackConfirmDialog. Цитата:
Если нужны для какого-то паблик метода, они могут быть переданы методу. Без передачи ссылки на верхний класс Вы не осуществите свою схему с подпиской мелкого на событие от старшего (и слава богу) и тем более отдельное Хранилище Всего (разве что статическое с импортом класса Хранилища во всех мелких – надеюсь об этом речи вообще не идет). Вобщем я хочу еще раз сказать, и надеюсь последний.. Весь кажущийся ужас передачи Вы придумываете себе сами, рассматривая кошерную передачу на фоне некошерной архитектуры. Когда иерархия выстроена правильно, никаких нелогичных передач не остается. Если симметрия ответственностей нарушена, добиться нужных связей можно только введением нелогичных членов и обходных путей передачи - хранилищ, менеджеров, провайдеров, прочих отростков. Надо стремиться к целостности и четкому разделению ответственности. Поэтому комментировать конкретные примеры/фрагменты бессмысленно. Будем бесконечно ходить по кругу. |
Цитата:
а attackConfirmDialog рисует в эту битмапдату диалоговое окно. По этому ссылка одному на другого не нужна - у них общая битмапдата. Сейчас саму битмапдату я положил в отдельный класс-хранилище и спускаю обоим в конструкторах. Но интуитивно понимаю, что это неправильно. |
Просто наверное лучше наоборот чтобы у объекта был метод getBitmapData, ну или там свойство BitmapData, класс родитель пробегался бы по всем объектам и рендерил бы каждый в "стэйдж" на который имеет ссылку. Или нет?
|
Цитата:
Добавлено через 1 минуту hvostoblud, ага. Это называется BitmapData#draw(). |
тогда получается что:
1. У каждого объекта, который нужно нарисовать, должна быть своя, локальная битмапдата, в которую он рисует, а рендер, пробегая по ним, уже рисует их на глобальный холст. Ну это я ещё могу понять, в принципе это логично. 2. Рендер должен знать обо всех объектах, которые нужно пробежать. Вот с этим ка быть? Допустим, волею судеб у мня все объекты интерфейса лежат в view.GUI и там распиханы по своим классам. Т.е. мне нужно делать массив ссылок на объекты, которые должны быть прорисованы или как? Как рендер узнает о них всех? |
Цитата:
|
| Часовой пояс GMT +4, время: 00:54. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.