Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Как делать ветвление структуры в MVC? (http://www.flasher.ru/forum/showthread.php?t=117866)

Gaen 08.11.2008 18:38

Как делать ветвление структуры в MVC?
 
Есть Document Class, в котором размещён код прелоадера. После загрузки создаётся класс Main, в конструкторе которого инициализируются модель, вью и контроллер. Контроллеру говорим грузить данные. Он говорит модели перейти в состояние "загрузка данных" и начинает грузить данные. Вью, получив от модели событие изменения состояния, показывает что грузятся данные.

Данные загрузились. Говорим модели перейти в основное состояние, она говорит об этом вью. А вот дальше...

Сайт имеет несколько модулей: для показа текста, для показа фоток итд. Каждый модуль так же грузит данные для своих нужд. В общем появляется понятие модуля.

Контроллер получает событие о переходе в основное состояние и в ответ на это говорит модели, какой модуль надо показывать. Модель в ответ на это посылает событие о том, что изменился активный модуль.

Итак, ситуация: всё загрузилось, в контроллер пришло событие что нужно показывать такой-то модуль.

Что делать дальше? Где должны располагаться модель, вью и контроллер модуля? Должны ли они быть обособлены, или каждая часть должна быть создана как дочерний объект глобальных M, V и С? Как передать им управление? Как организовать общение с главной связкой?

etc 08.11.2008 18:56

Создавайте отдельные MVC-структуры друг в друге, в соответствии с моделью display object на экране.

Gaen 08.11.2008 19:00

etc, вот я и пытаюсь понять, как запихивать их друг в друга. Что внутри чего должно быть?

etc 08.11.2008 19:16

Модель в модели, вьювер во вьювере. Контроллерам же обычно достаточно управлять на уровне корневых элементов.

Gaen 08.11.2008 19:19

Спасибо, буду пробовать и спрашивать вопросы по мере возникновения.

s8000_1 08.11.2008 22:39

__etc, а можно ли делать дочернее MVC полностью внутри вьювера?
Вот, например, у меня есть какой-нибудь хитрый контроллер-компонента, сделанный по принципу MVC, и я им хочу заменить стандартную кнопку. Он работает и без родительской модели автономно в принципе. Зачем его внутреннюю модель выносить наружу?

etc 08.11.2008 23:01

s8000_1, я не понял вопроса. Ни того, ни другого. Модель во вьювере не хранится, это первое. Внутреннюю модель тоже никто никуда не выносит, более того, не мешают модели, контроллеры и представления в одну кучу.

s8000_1 08.11.2008 23:30

__etc, разверну...

Есть визуальная AS3-компонента (типа DataGrid и т. п.) с понятным и логичным внешним интерфейсом. Но взаимодействие составных частей внутри компоненты устроено по принципу MVC: своя модель, свой внутренний контроллер и свое представление.

Я хочу эту компоненту прилепить к большому приложению (его представлению).
Получится, что MVC-компонента находится внутри представления другого MVC-большого приложения.

Это разве не правильно?

BlooDHounD 09.11.2008 03:33

s8000_1, ваще, если быть честным с общественностью, то DataGrid это чистый вьювер. ведь данные вы ему отдельно кормите? конечно всё зависит от реализации, но по идеологии он должен быть вьювером.

s8000_1 09.11.2008 04:07

BlooDHounD, так я как пример привел. Можно ведь соорудить гораздо более сложный компонент, для которого удобнее использовать внутри MVC (10 DataGrid'ов, 20 кнопочек и все это хитрым способом взаимодействует).

Поэтому я не совсем понимаю что значит "модель в модели".

etc 09.11.2008 12:48

Модель в модели означает древовидную структуру данных, по аналогии со структурой вьюверов. Т. е., скажем, есть общая структура данных датагрида, внутри неё лежат структуры данных с информацией о каждом элементе датагрида.
Датагрид, получая ссылку на общую структуру (DataGridData), создает DataGridItem-ы у себя внутри и раздает им DataGridItemData, а те, в свою очередь, отображают данные из DataGridItemData. Если изменилось значение какого-либо поля в DataGridItemData, то на это среагирует конкретный вьювер, не DataGrid (которому в принципе положить на это изменение, если он сортировкой не занимается, конечно), а DataGridItem. Контроллер же управляет всем этим компонентом, в котором и DataGrid и кнопки, и прочие контролы.

s8000_1 09.11.2008 14:28

__etc, понятно

А если датагрид по нажатию какой-либо кнопки внутри себя сортирует данные, то как это организовать: он должен посылать контроллеру событие "сортировка", модель сортирует данные и обновляет датагрид?

но ведь датагрид сам обновляется при сортировке данных =\

etc 09.11.2008 14:35

Нет, модель останется неизменной. А контроллер, если и принимает участие, только лишь в сохранении режима сортировки, а саму сортировку делает датагрид. Т. е. процесс сортировки за пределы датагрида не выходит, он всё делает сам, получает событие от своей же кнопки и т. д. При необходимости может выслать событие об изменении режима сортировки и всё.

s8000_1 09.11.2008 20:46

__etc, Спасибо, теперь все намного яснее :)
у меня вопрос еще такой по MVC (не хочется плодить темы)

Приложение создано для того, чтобы редактировать трансформации объекта на экране, менять их порядок и т. п. (графический редактор). Можно ли в модели хранить ссылки на конкретные объекты вместо массива матриц трансформаций?

etc 09.11.2008 20:49

На объекты какого рода?

s8000_1 09.11.2008 21:19

Ссылки на текстовые поля, битмапы.

Вместо того, чтобы хранить данные об объектах (координаты, матрицы трансформации, урлы картинок, текст текстового поля и др.) отдельно.
Или это уже кривой подход?

etc 10.11.2008 01:05

Модель должна хранить данные об объектах, а не ссылки на эти объекты.

Gaen 10.11.2008 03:09

У меня получилась вот такая вот модель, пока всем нуждам вполне удовлетворяет.

Код AS3:

package core{
 
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        //        IMPORTS
        ///////////////////////////////////////////////////////////////////////////////////////////////////
 
        import flash.events.EventDispatcher;
 
        import core.events.ModelEvent;
 
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        //        THE CLASS
        ///////////////////////////////////////////////////////////////////////////////////////////////////
 
        public class Model extends EventDispatcher{
 
                ///////////////////////////////////////////////////////////////////////////////////////////////////
                //        PRIVATE VARS
                ///////////////////////////////////////////////////////////////////////////////////////////////////
 
                private var vars        :Object;
 
                ///////////////////////////////////////////////////////////////////////////////////////////////////
                //        PUBLIC METHODS
                ///////////////////////////////////////////////////////////////////////////////////////////////////
 
                //constructor
                public function Model(){
 
                        super();
 
                        this.vars        =        {};
 
                }//constructor
 
                ///////////////////////////////////////////////////////////////////////////////////////////////////
 
                public function setVar(varName:String, varValue:*):void{
 
                        this.vars[varName]        =        varValue;
 
                        this.dispatchUpdated(varName);
 
                }//setVar
 
                ///////////////////////////////////////////////////////////////////////////////////////////////////
 
                public function getVar(varName:String):*{
 
                        try{
 
                                return this.vars[varName];
 
                        }catch(e){
 
                                return null;
 
                        }//try..catch
 
                }//getVar
 
                ///////////////////////////////////////////////////////////////////////////////////////////////////
                //        PRIVATE METHODS
                ///////////////////////////////////////////////////////////////////////////////////////////////////
 
                private function dispatchUpdated(varName:String):void{
 
                        var updateEvent                :ModelEvent                =        new ModelEvent(ModelEvent.UPDATE, varName, this.getVar(varName), true);
 
                        this.dispatchEvent(updateEvent);
 
                }//dispatchUpdated
 
                ///////////////////////////////////////////////////////////////////////////////////////////////////
 
        }//class
 
        ///////////////////////////////////////////////////////////////////////////////////////////////////
 
}//package


etc 10.11.2008 12:41

GAIKER, это плохая реализация. Это просто по факту неуправляемый объект с неизвестным количеством свойств.

Gaen 10.11.2008 13:07

etc, что подразумевается под неуправляемым?

Насчёт свойств - почему такой подход хуже, чем загромождать модель объявлением каждого свойства плюс геттера и сеттера для него?

etc 10.11.2008 14:13

Неуправляемый потому что туда может положить какие-угодно значения кто угодно.

А отсутствие геттеров и сеттеров — равносильно отсутствию типизации в коде.

Xpb7 10.11.2008 16:32

Думаю, было бы здорово открыть новый раздел, посвященный MVC. Обучение, примеры кода и т.д. Я несколько раз пытался въехать в этот фрэимворк, но пока выходит только чисто на интуитивном уровне.

etc 10.11.2008 16:43

MVC — это не фреймворк.

Xpb7 10.11.2008 17:17

Извиняюсь, а что же это тогда? Архитектура ПО, шаблон?

etc 10.11.2008 17:22

Шаблон.
Не путайте с фреймворком PureMVC.

Xpb7 10.11.2008 17:24

Именно с Pure и попутал. Надо будет произвести себе ликбез по этим делам.
А вы пользуетесь шаблонами или фрэимфорками (если честно пока не особо понимаю разницу)?

BlooDHounD 10.11.2008 17:27

__etc, даже не шаблон. скорее идеология.

Смольный (Smolniy) 10.11.2008 17:51

Лично я пользуюсь головой. :)

Для меня шаблоны (не только mvc, а всем пакетом) - концепция, не во всем отвечающая реальному миру, но полезная "для общего развития". Как законы Мерфи. ;) Как семиуровневая модель osi, не реализованная в каноническом виде никем, т.к. с практической точки зрения она не оптимальна.

s8000_1 14.11.2008 22:32

У меня назрел вопрос :rolleyes:

Допустим есть 2 элемента на экране: спрайт, который можно мышкой перетаскивать по экрану и текстовое инпут-поле, в которое можно забивать координаты этого спрайта.

В модели должны храниться только координаты этого спрайта, как я понимаю.

Вопрос касается событий. Как только мышкой передвигается спрайт на экране, то контроллер в модель пишет новые координаты, модель испускает событие CHANGE, которое слушает текстовое поле и соответственно в нем отображается координата модели. Однако же текстовое поле тоже может менять эту координату => CHANGE должен слушать и сам спрайт, изменяя соответственно свои координаты.

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

Как этого можно избежать?

etc 14.11.2008 22:37

Спрайт сам себя переносить не должен, его перемещение контролирует контроллер, изменяя значения координат в модели. Спрайт, получая события от модели, ставится в нужное место на экране. Т. е. спрайт является прямым отображением состояния модели.

s8000_1 14.11.2008 22:39

__etc, со спрайтом понятно.

А как быть с каким-нибудь List? Там selectedItem изменяется не извне контроллером, а изнутри все прописано.

etc 14.11.2008 22:46

Ну и что, что не изменяется? Тот же selectedIndex можно задать контроллером, в чём проблема? Значение индекса выбранного элемента можно хранить в модели, если это требуется сохранить. В противном случае индекс живет, пока живет контроллер.

s8000_1 14.11.2008 22:55

__etc, это понятно. Но я имею в виду примерно следующее:
Код AS3:

var controller:...
var model:...
 
var lst:List = new List();
addChild(lst);
lst.dataProvider = new DataProvider(...);
lst.addEventListener(Event.CHANGE, listChangeHandler);
model.addEventListener(Event.CHANGE, modelChangeHandler);
 
function listChangeHandler(e:Event):void{
  controller.setSelectedItem(lst.selectedItem); // => модель испустила CHANGE
}
 
function modelChangeHandler(e:Event):void{
 lst.selectedItem = model.getSelectedItem(); //и вот тут мы во второй раз пытаемся выставить selectedItem List'у, хотя мышкой оно уже выставилось
}

Как тут можно по-другому-то?

etc 14.11.2008 23:05

Для листа dataProvider-ом должна быть model. Это первое.
Второе: у контроллера не должно быть никаких публичных методов вообще, он должен сам создать лист (если требуется), отдать ему модель, сам подписаться на его события и менять модель.

s8000_1 14.11.2008 23:26

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

Пример - взаимодействие двух листов: выбираешь во втором => должно выбираться в первом и наоборот.

модель:
Код AS3:

private var _someData:XML = new XML(...);
public function get someData():XML { return someData; }

Контроллер:
Код AS3:

var lst1:List = new List();
addChild(lst1);
lst1.dataProvider = new DataProvider(model.someData);
lst1.addEventListener(Event.CHANGE, lst1ChangeHandler);
 
var lst2:List = new List();
addChild(lst2);
lst2.dataProvider = new DataProvider(bigModel.someData);
lst2.addEventListener(Event.CHANGE, lst1ChangeHandler);
 
function lst1ChangeHandler(e:Event):void{
 lst2.selectedItem = lst1.selectedItem;
}
 
function lst2ChangeHandler(e:Event):void{
 lst1.selectedItem = lst2.selectedItem;
}

Представление - это сами листы.

Правильно я понимаю?

etc 14.11.2008 23:34

Нет, неправильно. Хотя бы потому что у разных моделей ни один узел в одном XML не равен другому узлу из другого XML. Соответственно хендлеры работать не будут. Необходимо использовать либо selectedIndex (что обычно проще), либо находить по какому-то критерию от узла одного XML другой узел другого XML и ставить его в качестве selectedItem у второго листа. Безусловно, этим занимается контроллер.

s8000_1 14.11.2008 23:58

Все ясно, спасибо!

s8000_1 25.11.2008 01:26

__etc, очень извиняюсь но у меня опять назрел вопрос из той же серии. Все никак не могу понять...

1) А как быть с текстовыми полями? Например, контроллер - текстовое инпут-поле, рядом с ним кнопка. По нажатию на кнопку в модели апдейтится поле text, туда посылается переменная text из текстового поля. Но это же поле модели может изменить кто-либо другой => контроллер слушает события модели на предмет апдейта этого поля text.

По нажатию на кнопку я делаю апдейт модели. Модель испускает событие об изменении поля text внутри себя. Из-за этого события вызывается функция контроллера, которая апдейтит текстовое поле. Но оно уже изменилось до этого средствами флэша => эта функция вызвалась вхолостую.

2) А может ли контроллер быть наследником визуального класса, например Sprite?
Ведь чтобы расположить вьюверы на экране, нужны какие-то данные (хотя бы stage). Или width, height для того, чтобы расположить вьюверы каким-то определенным образом.

etc 25.11.2008 02:00

1) Это каким образом изменение модели прошло в обход контроллера? Контроллер, если и слушает изменение модели, то только лишь те изменения, которые требуют добавления/удаления вьюверов. В противном случае, изменения отслеживаются исключительно вьюверами. Ну а если подходить к возможным замкнутым рекурсиям, то в любом случае (в любом, это важно), в сеттере должна стоять проверка на текущее значение, типа if (this._somevalue === value) return;.

2) Он может иметь ссылку на контейнер-вьювер, но сам по себе визуальным объектом не может быть ни при каких обстоятельствах.

BlooDHounD 25.11.2008 02:45

__etc, ну зачем категорично? это комбо-система ... пример: любой уиконтрол :)


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

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