Архитектура приложения

Обсуждение и помощь по вопросам взаимодействия с ВКонтакте API в Flash-приложениях (ActionScript)
Agiliter
Сообщения: 112
Зарегистрирован: 01 фев 2014, 13:46

Re: Архитектура приложения

Сообщение Agiliter »

alexandr_ratush писал(а):Пример из контролера:

Код: Выделить всё

var _agentVK:AgentVK = new AgentVK(_model.socialData);
Благодарен за совет и разъяснение :)

В первоначальном варианте выдало ошибку, но было легко поправлено)

Код: Выделить всё

            var _data:Object = _model.getSocialData();            agentVK = new AgentVK(_data);
Agiliter
Сообщения: 112
Зарегистрирован: 01 фев 2014, 13:46

Re: Архитектура приложения

Сообщение Agiliter »

Мда. Слона-то и не заметил :D А как View "узнает" об изменении в модели? Если реализовывать паттерн Наблюдатель, то получается, что Модель - это издатель, а Представление - подписчик, я так понимаю. Если я верно мыслю, то в модели нужно создать массив, в который нужно занести всех возможных подписчиков, ну как минимум одно Представление. Потом в модели прописать метод, который бы вызывал у всех подписчиков метод апдейта. Но этот view будет же не тем же самым объектом, с которым будет работать контроллер. Или же в таком случае нужно в контроллере передавать view в модель? Вопрос оповещения об изменении модели очень интересен и важен для меня.
Аватара пользователя
alexandr_ratush
Сообщения: 94
Зарегистрирован: 05 мар 2014, 21:47

Re: Архитектура приложения

Сообщение alexandr_ratush »

В событийной модели флеш уже реализован паттерн Наблюдатель.
Или же в таком случае нужно в контроллере передавать view в модель?
Ни в коем случае. Вид должен обрабатывать данные модели и отображать их как ему угодно.
К примеру в модели есть данные для графиков. И у Виде вы можете отобразить их с помощью линий, столбиков, секторами кругов или как вам угодно. Это и есть свобода. :D

Принцип примерно такой:
1. После изменений данных в модели, отправляем событие в поток

Код: Выделить всё

dispatchEvent(new Event(SET_SOCIAL_DATA))
, для этого модель должна наследовать EventDispatcher.
2. У Виде мы подписываемся на модель

Код: Выделить всё

_model.addEventListener(SET_SOCIAL_DATA, setSocialHandler);
и обрабатываем их.
Agiliter
Сообщения: 112
Зарегистрирован: 01 фев 2014, 13:46

Re: Архитектура приложения

Сообщение Agiliter »

alexandr_ratush писал(а): У Виде мы подписываемся на модель

Код: Выделить всё

_model.addEventListener(SET_SOCIAL_DATA, setSocialHandler);
Вот опять) Получается, что в Вид передается модель? Как можно в Виде к _model адлистенер присобачить, если Модель и Вид общаются только через контроллер?
В Main:

Код: Выделить всё

             var view:View = new View();            var model:Model = new Model(data);             var controller:Controller = new Controller(view, model);            controller.init();            addChild(view);
А затем

Код: Выделить всё

         public function Controller(view:View, model:Model)         {            _model = model;            _view = view;         }                public function init():void         {            _model.init();            _view.init();            clientServer = new MyClientServer();            var data:Object = _model.getSocialData();            agentVK = new AgentVK(data);                    }
Не нужно ли тогда var view:View = new View(model)?
Agiliter
Сообщения: 112
Зарегистрирован: 01 фев 2014, 13:46

Re: Архитектура приложения

Сообщение Agiliter »

Или же после изменений данных в Модели, отправляем событие в поток, а на Модель подписываемся в Контроллере, который вызывает метод апдейта Вида :)
Аватара пользователя
alexandr_ratush
Сообщения: 94
Зарегистрирован: 05 мар 2014, 21:47

Re: Архитектура приложения

Сообщение alexandr_ratush »

Получается, что в Вид передается модель? Как можно в Виде к _model адлистенер присобачить, если Модель и Вид общаются только через контроллер?
Есть понятие активная и пассивная модель Википедия

Я в своих проектах использую активную модель.
Вот собственно код создания триады MVC
Main:

Код: Выделить всё

package {    import controllers.Controller;    import flash.display.Sprite;    import flash.events.Event;    import models.Model;    import views.View;        /**     * ...     * @author ratush     */    public class Main extends Sprite {                        public function Main():void {            if (stage) init();            else addEventListener(Event.ADDED_TO_STAGE, init);        }                private function init(e:Event = null):void {            removeEventListener(Event.ADDED_TO_STAGE, init);                                    var _model:Model;                        var _view:View = new View();                        var _controller:Controller = new Controller(_model, _view);                _controller.init();                            addChild(_view);        }            }    }
Controller:

Код: Выделить всё

package controllers {        import models.Model;    import views.View;        /**     * ...     * @author ratush     */    public class Controller {                private var _model:Model;        private var _view:View;                        public function Controller(model:Model, view:View) {            _model = model;            _view = view;        }                        public function init():void {            _model = Model.init();            _view.init(_model);        }            } }
Model:

Код: Выделить всё

package models {        import flash.events.EventDispatcher;        /**     * ...     * @author ratush     */    public class Model extends EventDispatcher {                //SINGLETON vars        private static var instance:Model;         private static var allowInstance:Boolean;                                public function Model() {                        if (allowInstance == false) {                 throw new Error("Error: use Model.init()");            }        }                /**         * Singleton function         * @return         */        public static function init():Model {                        if(instance == null) {                allowInstance = true;                instance = new Model();                allowInstance = false;            }             else{                trace("Singleton instance already exists.");            }            return instance;        }                            } }
View:

Код: Выделить всё

package views {        import flash.display.Sprite;    import models.Model;        /**     * ...     * @author ratush     */    public class View extends Sprite {                private var _model:Model;                                public function View() {                    }                public function init(model:Model):void {            _model = model;        }            } }
Agiliter
Сообщения: 112
Зарегистрирован: 01 фев 2014, 13:46

Re: Архитектура приложения

Сообщение Agiliter »

:shock: Большое спасибо :)

Хочу уточнить еще один момент. Реакцию на действия пользователя реализуем в Контроллере? Например, кнопки рисуются в Виде. А при нажатии что происходит? Нажатие кнопки, созданной в Виде должен обрабатывать Контроллер? Как?

А если такая реализация? Общая схема

Код: Выделить всё

 var _model:Model = new Model();var _controller:Controller = new Controller(_model);var _view:View = new View(_model, _controller);
Тогда пользователь приложения взаимодействует с элементом интерфейса пользователя (например, нажимает на кнопку в Виде).
Вид посылает соответствующее событие Контроллеру, чтобы он решил, как его нужно обработать. Что-то вроде

Код: Выделить всё

 btn.addEventListener(MouseEvent.CLICK, _controller.func);
Контроллер производит изменения в Модели на основе своего решения о том, как следует обработать это событие.

Код: Выделить всё

 _model.modify();
Модель информирует Вид об изменении своего состояния.

Код: Выделить всё

dispatchEvent(new Event(MODIFY_DATA));
Вид считывает информацию о новом состоянии и обновляет себя.

Код: Выделить всё

_model.addEventListener(SET_SOCIAL_DATA, update);
Или тут есть какой-то косяк, который моему неоптыному взгляду незаметен? :)
Alazaur
Разработчик
Разработчик
Сообщения: 1001
Зарегистрирован: 16 окт 2011, 20:25

Re: Архитектура приложения

Сообщение Alazaur »

Хочу уточнить еще один момент. Реакцию на действия пользователя реализуем в Контроллере? Например, кнопки рисуются в Виде. А при нажатии что происходит? Нажатие кнопки, созданной в Виде должен обрабатывать Контроллер? Как?
Agiliter, вьюшка диспатчит событие, контоллер его ловит и дергает модель. Основная суть здесь в том, чтобы сделать модель и вью обособленными. Выражение контроллер меняет модель несовсем верно. контроллер ничего не меняет в модели. Модель предоставляет ему некоторый ограниченный интерфейс открытых методов, после вызова которых она решит, что делать, как-то реагировать или нет.
Agiliter
Сообщения: 112
Зарегистрирован: 01 фев 2014, 13:46

Re: Архитектура приложения

Сообщение Agiliter »

ок. Общий принцип понял. Сделал простенькую тест программу на основе MVC. При нажатии кнопки View

Код: Выделить всё

btn.addEventListener(MouseEvent.CLICK, buttonClick);
диспатчит событие

Код: Выделить всё

dispatchEvent(new Event(EventTypes.SET_HP));
Контроллер его ловит

Код: Выделить всё

_view.addEventListener(EventTypes.SET_HP, setHP);
и вызывает метод Модели

Код: Выделить всё

_model.setHP();
Этот метод диспатчит событие

Код: Выделить всё

dispatchEvent(new Event(EventTypes.SET_HP));
которое ловит вьюшка

Код: Выделить всё

_model.addEventListener(EventTypes.SET_HP, viewHP);
Круг замкнулся :)
Делал на трейсах, и всё хорошо отработало. Но проблема в том, что кнопку пришлось делать прямо во View. Я до этого создавал класс MyWindow, который отвечает за создание полноценных окошек с кнопками. И поэтому хотел его и использовать для создания окошек во View?
private var myWindow:MyWindow;
myWindow.mainWindow();
Однако, в таком случае, когда нажатие на кнопку обрабатывается не прямиком во View (а в классе MyWindow, где и создается), я не знаю как диспатчить событие, чтобы контроллер его поймал. Если кнопка создается и описывается её реакцию во вьюшке, то без проблем, а если уже в классе MyWindow, то получается, что в контроллере нужна ссылка на MyWindow и независимость Вида и Контроллера теряется
Аватара пользователя
alexandr_ratush
Сообщения: 94
Зарегистрирован: 05 мар 2014, 21:47

Re: Архитектура приложения

Сообщение alexandr_ratush »

Как известно объекты из списка отображения имеют свойство оповещать что у них наступило событие (фазы захвата и всплытия).
Вы же можете в контролере подписать объект класса MyWindow на событие:

Код: Выделить всё

 _view.myWindow.addEventListener(EventTypes.SET_HP, setHP); 
И когда будет нажата кнопка, об этом узнает myWindow, _view и контролер.
а если уже в классе MyWindow, то получается, что в контроллере нужна ссылка на MyWindow и независимость Вида и Контроллера теряется
Подкину еще вам дровишек в огонь. :D Посмотрите в сторону патерна Медиатор. Может он вам поможет.
Ответить