Простой MVC фрэймворк
Понадобился мне вдруг MVC фрэймворк.
Поискал я в интернетах, нашел разных там "корнХулио" (с) Beaves и pureMVC, и понял что "чо-то мне как-то не так" (с) Бочарик
В общем решил написать свой мега простой фрэймворк))
Прошу любить и жаловать. А особенно замечания давать.
Итак :Часть первая. Цель.Структура фрэймворка. Интерфейсы
Начнем со структуры фрэймворка, и хотя изначально, было чуток по другому, в итоге мой проект стал выглядеть так:
Собственно папочка simpleMVC и есть мега фрэймворк.
Задачи фрэймворка: создать базовые классы и интерфейсы для реализации MVC.
Я начал с Интерфейса модели:
класс simpleMVC.models.IModel
Модель сама не является данными, для этого у нее есть свойство data. также модель должна диспатчить события, поэтому наследуем интерфейс IEventDispatcher
package simpleMVC.models { import flash.events.IEventDispatcher; /** * ИНтерфес представления модели * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public interface IModel extends IEventDispatcher { function get data():IModelData; function set data(__data:IModelData):void; function update():void; } }
класс simpleMVC.models.BaseModel
package simpleMVC.models { import flash.events.EventDispatcher; /** * Базовый класс модели * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public class BaseModel extends EventDispatcher implements IModel { /** * Данные модели */ private var _data:IModelData; public function BaseModel() { } public function get data():IModelData { return _data; } public function set data(__data:IModelData):void { _data = __data; update(); } public function update():void { trace ("update " + data); dispatchEvent(new ModelEvent(ModelEvent.CHANGE)); } } }
package simpleMVC.models { /** * Пустой интерфейс данных модели. * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public interface IModelData { } }
package { import remoteClasses.User; import simpleMVC.models.BaseModel /** * Модель данных о Юзере * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public class UserModel extends BaseModel { private var _data:User; } }
В реализации интерфейса модели возник ModelEvent.
package simpleMVC.models { import flash.events.Event; /** * Событие изменения модели * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public class ModelEvent extends Event { public static const CHANGE:String = "change"; public function ModelEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) { super(type, bubbles, cancelable); } } }
Часть вторая: View
Интерфейс для View:
package simpleMVC.views { import flash.events.IEventDispatcher; import simpleMVC.models.IModel; /** * Интерфейс для всех вьюшек. * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public interface IView extends IEventDispatcher { function get model():IModel; function set model(_model:IModel):void; //function update():void; } }
package simpleMVC.views { //import flash.display.MovieClip; //import flash.display.Sprite; import flash.events.EventDispatcher; import simpleMVC.models.IModel; import simpleMVC.models.ModelEvent; /** * Базовый класс моделей * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public class BaseView extends EventDispatcher implements IView //public class BaseView extends Sprite implements IView //public class BaseView extends MovieClip implements IView { private var _model:IModel; /** * Данные модели private var data:*; */ /** * Установка модели */ public function set model(__model:IModel):void { _model = __model; _model.removeEventListener(ModelEvent.CHANGE, update); _model.addEventListener(ModelEvent.CHANGE, update); } public function get model():IModel { return _model; } /** * Обновление представления * @param e Событие изменения модели */ private function update(e:ModelEvent):void { var data:String = String(e.target.data); trace (" BaseView.update: "+data); } public function BaseView() { super(); } } }
package simpleMVC.views { import flash.display.Sprite; import simpleMVC.models.IModel; import simpleMVC.models.ModelEvent; /** * ... * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public class BaseSpriteView extends Sprite implements IView { private var _model:IModel; /** * Данные модели private var data:*; */ /** * Установка модели */ public function set model(__model:IModel):void { _model = __model; _model.removeEventListener(ModelEvent.CHANGE, update); _model.addEventListener(ModelEvent.CHANGE, update); } public function get model():IModel { return _model; } /** * Обновление представления * @param e Событие изменения модели */ private function update(e:ModelEvent):void { var data:String = String(e.target.data); trace (" BaseSpriteView.update: "+data); } public function BaseSpriteView() { } } }
Часть третья. Контроллеры.
Самая наверное неоднозначная часть моего фрэймворка.
Контроллеры всего навсего сопоставляют пары MV и слушают V.
Интерфейс:
package simpleMVC.controllers { import flash.events.IEventDispatcher; import simpleMVC.models.IModel; import simpleMVC.views.IView; /** * Интерфейс контроллера * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public interface IController extends IEventDispatcher { function addModelViewer(__model:IModel, __view:IView):void; function changeModel(__model:IModel, __data:*):void; function addViewEventListener(__view:IView, e:String, handler:Function):void; function removeViewEventListener(__view:IView, e:String, handler:Function):void; } }
package simpleMVC.controllers { import flash.events.EventDispatcher; import simpleMVC.models.IModel; import simpleMVC.views.IView; /** * Базовый класс контролллеров * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public class BaseController extends EventDispatcher implements IController { public function BaseController() { } /** * Добавить вьювер к модели * @param __model Модель * @param __view Представление */ public function addModelViewer(__model:IModel, __view:IView):void { __view.model = __model; } /** * Изменить данные модели * @param __model * @param __data */ public function changeModel(__model:IModel, __data:*):void { __model.data = __data; } /** * Назначить слушатель представления * @param __view * @param e * @param handler */ public function addViewEventListener(__view:IView,e:String, handler:Function):void { __view.addEventListener(e, handler); } /** * Удалить слушатель представления * @param __view * @param e * @param handler */ public function removeViewEventListener(__view:IView,e:String, handler:Function):void { __view.removeEventListener(e, handler); } } }
package remoteClasses { /** * Класс данных модели Юзера. Объект класса передается с сервера в сериализованном виде * @author k0t0vich (c) 2009 b_konstantin@list.ru */ public class User { public var id:int = 1; public var name:String = "peter"; public function User(_id:int,_name:String) { id = _id; name = _name; } public function toString():String { return ('[User id='+String(id)+' name="'+name+'"]'); } } }
package { import simpleMVC.controllers.BaseController; import flash.display.Sprite; import flash.events.Event; import simpleMVC.models.ModelEvent; import simpleMVC.views.BaseView; import simpleMVC.views.BaseSpriteView; import remoteClasses.User; /** * Тестирование MVC * класс фасада (бизнес контроллер) * @author k0t0vich (c) 2009 b_konstantin@list.ru http://islandsworld.ru/ */ public class Main extends Sprite { public var userModel:UserModel; public var baseView:BaseView; public var baseSpriteView:BaseSpriteView; public var baseController:BaseController; 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); // entry point userModel = new UserModel(); // простая вьюшка наследуется от EventDispatchera baseView = new BaseView(); // вьюшка наследуемая от спрайта baseSpriteView = new BaseSpriteView(); // базовый контроллер baseController = new BaseController(); //Инициализация связки MV - назначение для вью модели baseController.addModelViewer(userModel, baseView); baseController.addModelViewer(userModel, baseSpriteView); // Изменение модели. Имитация поведения серверного контроллера baseController.changeModel(userModel, new User (12, "Bob")); // добавляем слушатель baseController.addViewEventListener(baseSpriteView, Event.ADDED_TO_STAGE, baseSpriteViewAddedtoStageListener); //добавляем сппрайтовую вьюшку на сцену addChild(baseSpriteView); } // команда назначенная контроллерам на событие спрайт-вьюшки private function baseSpriteViewAddedtoStageListener(e:Event):void { trace ("baseSpriteViewAddedtoStageListener: "+e); } } }
// в итоге получаем: /* update [User id=12 name="Bob"] BaseView.update: [User id=12 name="Bob"] BaseSpriteView.update: [User id=12 name="Bob"] baseSpriteViewAddedtoStageListener: [Event type="addedToStage" bubbles=false cancelable=false eventPhase=2] */
Что еще надо?
исходники mvc.rar:
Всего комментариев 7
Комментарии
08.04.2009 18:32 | |
Спасибо за статью, я только недавно заинтересовался ооп, может быть мой вопрос покажется не очень умным, но я в упор не могу понять для чего применяются все эти интерфейсы?
|
09.04.2009 14:32 | |
Скажу может не по-научному, но по-простому)
пример: имеем основной класс который подгружает модули, для каждого модуля нужно вызвать метод, например, draw. Определяем интерфейс IDrawable, в котором есть метод draw, все модули должны реализовывать этот интерфейс, т.е. у них должен быть метод draw. Загрузочный класс загружает модель и работает с ним как с объектом класса IDrawable - реальные классы модулей могут быть любые, главное чтоб реализовывали интерфейс. |
|
Обновил(-а) Котяра 09.04.2009 в 14:35
|
07.04.2011 00:02 | |
Небольшое упущение во вьюшках нет проверок на отсутствие модели при removeEventListener
|
07.04.2011 00:17 | |
Да тут много косяков.
|
13.03.2012 20:16 | |
Да.
Записи 3 года скоро будет. Цитата:
Да тут много косяков.
|
Последние записи от Котяра
- Страх и ненависть в Нью-Дели или сборка мультипака для arm7 и x86 c Adobe AIR 14 в FB (16.06.2014)
- Нативный EventDispatcher в старлинге (27.11.2013)
- Нужны ошибки компиляции при создании экземпляра синглетона извне? Запросто! (13.09.2013)
- ARP - новый формат упаковки ресурсов (07.02.2013)
- DropShadowFilter и GlowFilter в Starling (16.01.2013)