Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Psycho Tiger

Рейтинг: 4.79. Голосов: 19.

MVC, часть 1: про дубовый стол и сиськи

Запись от Psycho Tiger размещена 30.10.2010 в 02:36
Обновил(-а) Psycho Tiger 14.12.2010 в 18:10

[Что-то очень глючил редактор, где то возможны нестыковки - текст порой просто удалялся. Замечания пишите в комменты. Спасибо]

...и вот появился на свет гений. Истинный Разработчик. Луч света падает на него, а клавиатура сокрушается под ударами его пальцев... Сейчас он сядет и сделает шедевр, в ритмах Вивальди извлекая звуки от щелчков мышки и ритмичных ударов о клавиатуре...

Думайте это о Вас? Обо мне? Пфф... Это Вам не сага о Горце. Тут придется включить свою голову. Ну или хотя бы сделать вид. Как бы то ни было - купите виски и откиньтесь на спинку кожаного кресла, положив свои ноги в ботинках из крокодиловой кожи на стол из столетнего дуба. Да-да, вы не ослышались. MVC - это действительно круто. Соплякам тут не место )

Мне всегда вот в научных статьях, учебниках по квантовой физике и статьях на википедии не нравилось одно - сухость материала. Ну пришел Шредингер, сказал что нашел универсальное уравнение в материи в целом - и понеслись иероглифы. Ну вот как это следует вообще понимать? Тут тоньше надо. Не спугнуть читателя, объяснять всё простым языком... Тут тренд Дисковери уловил, конечно. Поэтому давайте-ка я расскажу вам о трёх буквах.

Готовы? Отлично, так рад видеть на Ваших лицах заинтересованность - вот оно, "эм вэ цэ" да ещё и языком художественным текстом, где возможно. Только сразу огорчу - про дубовые столы я погорячился. Точнее, не погорячился, а совсем соврал. Это полная чушь, что MVC что-то там даёт. Да-да, я вас сильно обманул, но обещаю, что больше так делать не буду, а вы мне взамен обещайте что будете слушать меня внимательно. Договорились? Договорились. Дак вот, MVC - это просто инструмент, он не сделает из Вас ни "тру-флешера", ни человека способного на что-то большее, чем он умел до этого. Скажу больше, удобство использования вы ощутите... ну после нескольких недель работы. Это как накачать пресс - жирок то родной, булочки вкусные, а тренажеры не манят. Зато потом сверкая прессом перед девочками на пляже... ну вы поняли. Не испугались? Тогда вперёд )

Начнем, пожалуй, с истории среднестатистического флеш-разработчика. Речь, конечно же, пойдёт о человеке растущим на флеше с 0, а не матёрым Java`ером, который решил переквалифицироваться.

Сперва разработчик начинает писать свой код в кадрах/в одном классе. Он не понимает, зачем создавать другие классы, ведь всё можно написать здесь - и оформить функцией - то есть замыканием. Некоторые о приёме замыкания не знают - и слава богу - и пишут в методах.
Наступает момент, когда кода становится слишком много и под давлением общественности человек начинает делать попытки создавать другие классы. И тут же чувствует себя скованным - как же получить глобальную переменную... В следствии чего в конструктор пихает всё что только может. А ещё лучше - ссылку на класс, который его и создал. В итоге Main порождает пятерку других классов. И все знают всё о Main.
Потом человек понимает, что так передавать - крайне неэффективно. И начинает использовать синглтон. Ну как синглтон... Он думает, что это синглтон. На самом деле - просто набор статический методов и переменных. Ну должен же быть глобальный контроль!

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

И вот только потом, через много времени он чувствует себя готовым. Готовым к большим открытиям и большим наградам. И виднеются на горизонте три большие, заглавные буквы - M, символизирующие Молодец разработчику, V, символизирующее пятерку за архитектуру и C - символизирующее Сиськи, которых порой так не хватает рядом во время длительной разработки. Ну, это для меня. MVC - у каждого своё. Вроде бы очевидно, что от MVC со временем не так то просто отказаться.


...Затянулось начало. Перейдём к делу.
Чтобы было сразу понятней - сразу же введем пример. Предположим, у нас есть герой у которого есть 3 вида оружия. Вид игры - сверху.
Рассмотрим отдельно все части:
M - Model. Модель. Хранит данные, которые нужны триаде (MVC). Это - координаты игрока в мире, текущие оружие в руках, количество здоровья, количество боеприпасов. Остальные данные - например количество крови хлыщущее из его вены в модели не хранятся.

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

C - Controller. Контроллер. Он занимается логикой всей триады. Именно он обрабатывает нажатие клавиш и меняет данные в модели, записывая туда новые координаты игрока. Именно он разрешает игроку стрелять и меняет у него оружие.

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

Сейчас я дам вам картинку, нагло взятую где то из интернета.


Какая прелесть, правда? Давайте разберемся. Сплошными линиями показаны жесткие связи между трио - то есть у контроллера есть прямая ссылка на модель и на вьюшку, а у вьюшки на модель. Штрихованными же показано кто кого слушает - контроллер слушает вьюшку, а вьюшка модель. Что такое "слушает" - ниже, на примере каждого.

Пример с игрой и человечком сверху был удачным для объяснения идеи текстом, но мне кажется для практической реализации нужно взять пример попроще. Давайте сделаем совсем элементарный пример: несколько квадратиков, все разных цветов. При этом есть одна стрелочка, которая указывает на один из квадратов. По клику стрелочка указывает на случайный квадратик, а каждые 3 секунды цвета у квадратов меняются. Это игра будет для детей дошкольного возраста: они должны будут произносить вслух цвет, на который указывает стрелочка, а воспитатель скажет, правильно или нет.
Итак. Сперва мы должны создать Главный контроллер - он всегда самый главный в любом приложении. У нас будет всего один контроллер, одна модель и одна вьюшка - поэтому контроллер главный, и по совместительству единственный. Контроллеру нужно знать, куда добавлять всю прелестную графику? Нужно. Поэтому ему нужен иметь какую-то точку привязки для графики - DisplayObjectContainer. Где её взять? Это - ваш класс Main, который базовый. Как создать главный контроллер? В Main, в конструкторе или в обработчике события Event.ADDED_TO_STAGE нужно написать примерно следующее:
Код AS3:
new BaseController(this);
Мы просто создали этот контроллер и передали ссылку на себя - то есть на то место, где будет скапливаться вся графика. Нам даже не нужно сохранять ссылку на главный контроллер!
Код класса BaseController:
Код AS3:
package
{
	import flash.display.DisplayObjectContainer;
 
	public class BaseController
	{
		private var _host:DisplayObjectContainer;
		private var _model:Model;
		private var _view:View;
 
		public function BaseController(host:DisplayObjectContainer)
		{
			super();
			_host = host;
			_model = new Model();
			_view = new View(_model);
 
		}
 
	}
 
}
Что мы сделали? Мы просто в конструкторе сразу же создали и модель, и вьюшку.
Давайте напишем модель. Сперва нужно понять, что должно быть в модели. В модели должны быть данные, которые нужны всей триаде. Это - цвета всех квадратов и номер квадрата, на который указывает стрелочка. "А как же графика для стрелочки, размеры квадрата, расстояние между ними и всё остальное?" - воскликнет читатель. Нет, эти данные не должны хранится в модели. Вся графика, все звуки и всё остальное - это забота вьюшки, в этом и прелесть: сегодня у меня на экране человек, а завтра киборг. При этом я переписываю только отображение, не трогая контроллер и модель, тем самым не "ломая" логику. Размер прямоугольников - не нужен в контексте этой задачи - нам плевать на форму, хоть квадратная, хоть скругленная. Нам так же плевать на позиции - хоть синусоидально, хоть по прямой. На логику это не влияет. Нам просто нужно выводить на экран какие-то цветные элементы и помечать их. Отсюда всплывает очередная прелесть - мы можем не сильно заботится о том, что творится на экране, оставив это на "потом". Будь другой контекст - например, если бы нужно было отгадать размер в пикселах этой фигуры - то эти данные попали бы в модель. Аналогично и с формой, и с расположением. Проще говоря, в модели хранятся значимые данные в данной задаче. А на фоне гусей или океана это происходит - программу не колышет.

Итак, нам нужно хранить в модели массив цветов и номер прямоугольника, на который указывает стрелка. При этом при изменении информации в модели неплохо было бы заявить всем желающим, что данные изменились - неплохо бы их обновить. Это означает, что модель должна испустить событие о том, что она изменилась. Делается это GoF паттерном Observer, но не пугайтесь: обычная событийная флешевая событийная модель реализует именно его, поэтому нам совсем не стоит об этом беспокоится. При обновлении информации есть 2 подхода: push и pull. При обновлении информации мы генерируем событие о том, что что-то изменилось. Представим, что это событие кто-то поймал. В событии может содержаться вся информация о том, что же изменилось - такой подход называется push - мы проталкиваем с событием всё что нужно обновить. Другой подход - pull - значит "тяни". В таком случае события носят нотификационный характер - что-то вроде "Эй парень, число народу в игре обновилось.". А сколько теперь онлайн - это событие не скажет. И в таком случае эти данные приходится "тянуть" с модели явно. Я использую оба подхода, оба подхода хороши. Но конкретно сейчас я ограничусь pull-подходом. Кстати, событийное поведение добавляет ещё одно удобство, одно из главных - если у нас в 5 разных местах показывается, например, баланс игрока - то при изменении баланса в одном месте он должен поменяться во всех.
Но тут всплывает проблема: поменяв номер прямоугольника, на который указывает стрелочка вызовется сеттер, который испустит событие об изменении. Но в случае с массивом всё не так: чтобы вызвать сеттер у массива нужно будет переопределить на него ссылку, что недопустимо: нам нужно просто менять элементы массива, но не ссылку на него. Решений у проблемы несколько. Например, самый извращенный - это унаследовать модель от Proxy, определив там поведение для [], попутно реализовав ей IEventDispatcher. Можно, например, сделать метод setElement, в теле которых и генерировать событие об изменении. Можно в модели добавить метод "сделай событие пожалуйста, что ты изменилась" и дёргать его. Но немного подумав вспоминаем, что модель мы меняем в контроллере. А в контроллере мы имеем полный контроль над вьюшкой. Поэтому в этом случае на мой взгляд самым лучшим решением будет явно вызвать метод у вьюшки после того как закончится изменение модели.
Код Model:
Код AS3:
package  
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
 
	[Event(name="change", type="flash.events.Event")]
	public class Model extends EventDispatcher implements IReadableModel
	{
 
		private var _pointer:int = 0;
		public var colors:Array = [];
		public function Model() 
		{
			super();
		}
 
		public function get pointer():int { return _pointer; }
 
		public function set pointer(value:int):void 
		{
			if (_pointer == value) return;
			_pointer = value;
			super.dispatchEvent(new Event(Event.CHANGE));
		}
 
	}
 
}
Теперь сделаем вот такой вот финт в голове: абстрагируемся от трио и посмотрим только на модель. Просто храним данные, по возможности говорим всем желающим событием о том, что данные изменились. Ничего сложного, ведь так?

Итак, теперь View. Как мы поняли ранее, у View есть прямая ссылка на Model, в итоге нам нужно всего лишь визуализировать эти данные.
Код AS3:
package  
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class View extends Sprite 
	{
		private var _model:Model;
		private var _squares:Array;
		private var _pointer:Shape;
 
		public function View(model:Model) {
			super();
			_model = model;
			 //здесь будем хранить ссылки на созданные графические объекты
			_squares = [];
			//это типа стрелочка
			_pointer = new Shape(); 
			_pointer.graphics.beginFill(0x00FF00);
			//круглая такая стрелочка
			_pointer.graphics.drawCircle(0, 0, 30); 
			_pointer.y = 100;
			_pointer.graphics.endFill();
 
			super.addChild(_pointer);
 
			//вызываем обработчик как будто-бы модель изменилась. Это нужно чтобы указатель
			//сразу встал на нужный квадрат
			onPointerChange(null);
 
			 //подписались на изменение модели
			_model.addEventListener(Event.CHANGE, onPointerChange);
		}
 
 
		public function updateSquares():void {
			//поменялись цвета - удаляем все старые прямоугольники
			var i:int = _squares.length;
			while (i--) super.removeChild(_squares.pop());
			//рисуем новые
			i = _model.colors.length;
			while (i--) {
				var shape:Shape = new Shape();
				shape.graphics.beginFill(_model.colors[i]);
				shape.graphics.drawRect(0, 0, 50, 50);
				shape.graphics.endFill();
				shape.x = 100 * i;
				_squares.push(shape);
				super.addChild(shape);
			}
		}
 
		private function onPointerChange(event:Event):void {
			_pointer.x = 100 * _model.pointer;
		}
 
	}
 
}
Мы рисуем квадраты - по цветам из массива, который хранится в модели и стрелочку, которая после конца кризиса набрала килограммов и стала круглой, заставляя её указывать на какой-то из квадратов. Какой - всё так же заявлено в модели.
Абстрагируемся. Нам сообщают событиями о том, что модель изменилась. Если мы получили такое сообщение - меняем изображение, чтобы быть актуальным каким-то данным, которые есть в модели. Попутно имеем паблик метод updateSquares, который будет вызван кем-то сверху, когда нужно обновить квадраты. Если не думать о трио в целом, а только об одном элементе - всё очень просто.
Резюме. Мы имеем что-то, что предоставляет нам данные и говорит, когда данные поменялись. На основе этого мы строим изображение. Всё просто? Отлично. Теперь связываем в голове модель и вьюшку. Связываем, думаем.

Готовы продолжать? Теперь контроллер.
Задача контроллера - менять модель. Просто писать в неё данные. Абстрагируемся вновь. Мы просто делаем какую-то логику, и пишем её в объект, не задумываясь о том что происходит дальше. Но ещё нам нужно вот что сделать в контроллере: добавить вьюшку в дисплай лист - т.е. просто сделать addChild к тому, что мы передали в конструктор главному контроллеру. По условию задачи менять каждые 3 секунды цвета. Что-ж, ничего сложного! Делаем:
Код AS3:
package  
{
	import flash.display.DisplayObjectContainer;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
 
	public class BaseController 
	{
		private var _host:DisplayObjectContainer;
		private var _model:Model;
		private var _view:View;
 
		public function BaseController(host:DisplayObjectContainer) 
		{
			super();
			_host = host;
			_model = new Model();
			_view = new View(_model);
 
			//создали таймер и запустили
			var _timer:Timer = new Timer(3000);
			_timer.addEventListener(TimerEvent.TIMER, onTimer);
			_timer.start();
 
			//сразу же вызвали обработчик, чтобы сразу при запуске забить массив
			//случайными квадратами
			onTimer(null);
 
			//добавили в дисплай лист - чтобы мы смогли увидеть работу вьюшки
			host.addChild(_view);
		}
 
		private function onTimer(event:TimerEvent):void 
		{
			//забиваем модель случайными цветами
			var i:int = 5;
			while (i--) {
				_model.colors[i] = int(Math.random() * 0xFFFFFF);
			}
 
			//говорим, что мы изменили цвета
			//это как раз тот момент из за невозможности вызова геттера
			_view.updateSquares();
		}
 
	}
 
}
И снова пытаемся представить контроллер как нечто "не связанное" с моделью и вьюшкой логически. Да-да, мы уже абстрагировались ещё перед написанием, но давайте не ленится. Если у вас получается, то он снова кажется простым - всего лишь меняем массив в каком-то объекте каждые 3 секунды. После этого пытаемся представить целостную картину, но это не всё. Мы не сделали интерактивность: стрелка (в нашем случае это круг) всегда будет указывать в одно место, а нам же необходимо чтобы стрелочка меняла положение на случайное по клику. Напоминаю, что это положение находится в модели.
Как это сделать? Наверное вам в голову лезет мысль - в контроллере отлавливать клик и менять модель. Нет, это не совсем правильно: это лепка программы "под конкретный вариант", а это как раз то, против чего создано MVC. Пользователь с чем взаимодействует? Только с вьюшкой. Он не может кликнуть по модели или по контроллеру - он кликает по экрану, что по сути является вьюшкой. Значит клик должна обрабатывать вьюшка. При этом это слишком связано, что именно по клику: сегодня по клику, завтра по нажатию клавиши, а послезавтра вообще по голосовой команде. Вьюшка должна сообщить о том, что надо бы поменять стрелочку - а уж отчего вьюшка так решила знает только она сама. В итоге во View дописываем функционал, что по клику диспатчим какое-то событие, которое слушает контроллер. Я опять буду использовать событие Event.CHANGE - поначалу могут возникнуть сложности - как же так, мы ведь его уже используем в модели - но это здорово развивает абстракцию. В реальных проектах типов событий у меня очень часто больше 30-40, тут, конечно, одним Event.CHANGE не обойтись и я делаю свой класс, расширяющий Event. Однако, какой случай - такой и инструмент, поэтому здесь Event.CHANGE.
Код AS3:
package  
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
 
	[Event(name="change", type="flash.events.Event")]
	public class View extends Sprite 
	{
		private var _model:Model;
		private var _squares:Array;
		private var _pointer:Shape;
 
		public function View(model:Model) {
			super();
			_model = model;
			 //здесь будем хранить ссылки на созданные графические объекты
			_squares = [];
			//это типа стрелочка
			_pointer = new Shape(); 
			_pointer.graphics.beginFill(0x00FF00);
			//круглая такая стрелочка
			_pointer.graphics.drawCircle(0, 0, 30); 
			_pointer.y = 100;
			_pointer.graphics.endFill();
 
			super.addChild(_pointer);
 
			//вызываем обработчик как будто-бы модель изменилась. Это нужно чтобы указатель
			//сразу встал на нужный квадрат
			onPointerChange(null);
 
			 //подписались на изменение модели
			_model.addEventListener(Event.CHANGE, onPointerChange);
 
			//нам должен быть доступен stage
			super.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}
 
		private function onAddedToStage(event:Event):void 
		{
			super.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			//подписались на заветный click
			super.stage.addEventListener(MouseEvent.CLICK, onClick);
		}
 
		private function onClick(event:MouseEvent):void 
		{
			//и выпустили событие
			super.dispatchEvent(new Event(Event.CHANGE));
		}
 
		public function updateSquares():void {
			//поменялись цвета - удаляем все старые прямоугольники
			var i:int = _squares.length;
			while (i--) super.removeChild(_squares.pop());
			//рисуем новые
			i = _model.colors.length;
			while (i--) {
				var shape:Shape = new Shape();
				shape.graphics.beginFill(_model.colors[i]);
				shape.graphics.drawRect(0, 0, 50, 50);
				shape.graphics.endFill();
				shape.x = 100 * i;
				_squares.push(shape);
				super.addChild(shape);
			}
		}
 
		private function onPointerChange(event:Event):void {
			_pointer.x = 100 * _model.pointer;
		}
 
	}
 
}
Это полный код View. Просто дописали, что по клику происходит испускание события Event.CHANGE.
Теперь немного перепишем контроллер:
Код AS3:
package  
{
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
 
	public class BaseController 
	{
		private var _host:DisplayObjectContainer;
		private var _model:Model;
		private var _view:View;
 
		public function BaseController(host:DisplayObjectContainer) 
		{
			super();
			_host = host;
			_model = new Model();
			_view = new View(_model);
 
			//создали таймер и запустили
			var _timer:Timer = new Timer(3000);
			_timer.addEventListener(TimerEvent.TIMER, onTimer);
			_timer.start();
 
			//сразу же вызвали обработчик, чтобы сразу при запуске забить массив
			//случайными квадратами
			onTimer(null);
 
			//добавили в дисплай лист - чтобы мы смогли увидеть работу вьюшки
			host.addChild(_view);
 
			//подписались на событие, по которому нужно изменить модель
			_view.addEventListener(Event.CHANGE, onViewChange);
		}
 
		private function onViewChange(event:Event):void 
		{
			//просто случайная позиция для стрелочки
			_model.pointer = Math.random() * 5;
		}
 
		private function onTimer(event:TimerEvent):void 
		{
			//забиваем модель случайными цветами
			var i:int = 5;
			while (i--) {
				_model.colors[i] = int(Math.random() * 0xFFFFFF);
			}
 
			//говорим, что мы изменили цвета
			//это как раз тот момент из за невозможности вызова геттера
			_view.updateSquares();
		}
 
	}
 
}
Тут тоже всё банально и просто - как только поймали событие Event.CHANGE от View - сразу же поменяли модель, которая в свою очередь побудила измениться отображению. Такой круговорот получится - View - Controller - Model - View. Забавно, правда?

Теперь пролистните вверх и посмотрите снова на картинку и вновь перечитайте часть, где я рассказывал про связи между M, V и C (Model, View и Controller). Теперь всё куда понятней, не правда ли?

Но и это не всё.
View не может изменять Model, как вы уже поняли, а у нас может. Как это исправить? Вью нужно передавать не саму модель, а только интерфейс, в которым "порезаны" все set методы. Например, в нашем случае такой:
Код AS3:
package  
{	
	public interface IReadableModel 
	{
		function get pointer():int; 
		function get colors:Array;
	}
 
}
(необходимо будет добавить геттер colors в Model)
Однако, мы всё равно можем изменить элемента массива colors. Можно, конечно, придумать метод getElementAt, который бы лез в массив и возвращал элемент на заданной позиции, тем самым запретив изменять элементы массива... однако запрет на изменение модели не имеет другого характера, кроме как "защиты от дурака/запарки", чтобы случайно вы сами не поменяли модель. Мне не было бы стыдно оставить интерфейс в виде, который я привёл чуть выше - если вы не доверяете себе или людям, с которыми работаете - пишите метод. Это - инструмент, и он должен подстраиваться под вас, а не вы под него. Не стесняйтесь смотреть на картинку - она сильно помогает первое время. Если она даже сейчас кажется вам сложной - не смотрите на неё, а читайте текст и рисуйте эту картинку у себя на бумажке. Не ленитесь, это действительно помогает.

На этом я закончу первую лекцию. В следующих мы будем ветвить контроллеры, делать иерархические модели, общаться с сервером. В общем, в следующие разы будет действительно интересно. Stay tuned

Вторая часть.
Всего комментариев 231

Комментарии

Старый 30.10.2010 07:05 andrew911 вне форума
andrew911
Спасибо за отличный урок!

На простых случаях все понятно, а вот на более сложных проектах возникает куча вопросов с реализацией, поэтому жду продолжения
Старый 30.10.2010 11:23 Division вне форума
Division
 
Аватар для Division
Очень хорошо написал. Но тема сисек до конца не раскрыта.
Да, еще неплохо было бы добавить исходники отдельным архивом.
Старый 30.10.2010 13:39 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Сиськи, сиськи... В девушке главное не сиськи, а правильное сочетание размеров и форм сисек с остальными параметрами (талия, бёдра и прочее)

Статья довольно интересная. В коде тоже важно правильное сочетание, и использование MVC наряду с шаблонами может позволить сделать значительный шаг в эту сторону.
Обновил(-а) f.g.programmer 30.10.2010 в 13:46
Старый 30.10.2010 13:45 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Мы о MVC говорим, не? Да и потом, я не говорил что сиськи женские
MVC он такой... коварный )
Старый 30.10.2010 13:53 Котяра вне форума
Котяра
 
Аватар для Котяра
Молодец. Пятёрка за Сиськи.
Старый 30.10.2010 14:56 cleptoman вне форума
cleptoman
 
Аватар для cleptoman
в общем все понравилось, но:

- а почему бы вьюхе вообще ниче не дать по модели, а менять вьюху из контролера по событию модели.
- пример простой..интересно почитать продолжение..с несколькими триадами и связи между собой (именно иерархически неравные триады, если я вообще уловил правильно суть MVC).

в остальном - спасибо.
Старый 30.10.2010 15:17 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Цитата:
- а почему бы вьюхе вообще ниче не дать по модели, а менять вьюху из контролера по событию модели.
Как было описано выше, может быть 5 окон, в каждом из которых отображаться баланс игрока. Если менять вьюху из контроллера - придется в 5 контроллерах её менять. В случае события от модели - меняем баланс и не задумываемся ни о чем - вьюхи сами его поменяют. Или речь о том, чтобы контроллер слушал модель и менял по этому запросу вьюху? Тогда это лишний переброс потока информации через контроллер.
Старый 30.10.2010 17:19 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Возможно, cleptoman имел в виду, что, когда мы меняем модель из контроллера, мы не здесь же меняем вьюхи, а бросаем событие из модели. Вьюхи слушают это событие и обновляются (это как раз на случай множественного представления)
Старый 30.10.2010 17:25 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Это неудобно - мне придётся помнить какое событие нужно кинуть меняя модель из контроллера, при этом собственно не забывая его кинуть.
Старый 30.10.2010 18:05 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Почему неудобно? Вполне логично завести в модели такой метод
Код AS3:
function changeColors():void {
    var i:int =  _colors.length;
    while (--i) {
         _colors[i] = int(Math.random() * 0xFFFFFF);
    }
    dispatchEvent(new Event("change_colors"));
}
вызывать его в котроллере
Код AS3:
private function onTimer(event:TimerEvent):void {
    _model.changeColors();
}
ну и обновлять представления на событие "change_colors" (само собой для "change_colors" нужно завести константу)
Обновил(-а) f.g.programmer 30.10.2010 в 18:12
Старый 30.10.2010 18:12 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
А, Вы про это. В данном конкретном случае - допустимо. В общем же случае решение о цветах, как и всякое другое решение, должно происходить в контроллере, то что они случайные - это частность.
Старый 30.10.2010 18:35 MrPoma вне форума
MrPoma
 
Аватар для MrPoma
Если частей несколько, обычно оглашают весь вписок, пожалуйста :-)
Старый 30.10.2010 19:25 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Я вообще думал что одна часть будет. Но потом понял, что многовато будет для одной статьи и решил разбить. Будет 2 или 3
Старый 31.10.2010 08:08 Slip_91 вне форума
Slip_91
 
Аватар для Slip_91
печально то как. я еще только на этапе "...думает, что это синглтон.." ))
Старый 31.10.2010 18:26 derhab вне форума
derhab
 
Аватар для derhab
Цитата:
Код AS3:
public interface IReadableModel 
{
	public function get pointer():int; 
	public var colors:Array;
}
это интерфейс такой?)
Старый 31.10.2010 19:00 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Да. Что смешного?
Старый 31.10.2010 19:34 derhab вне форума
derhab
 
Аватар для derhab
public перед function не употребляется также..
да ниче смешного, это просто не скомпилируется
Старый 31.10.2010 19:52 Hauts вне форума
Hauts
 
Аватар для Hauts
Артём, отлично. Привет.)
Старый 31.10.2010 19:55 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Цитата:
public перед function не употребляется также..
да ниче смешного, это просто не скомпилируется
Оу-оу. Действительно, это я что-то увлёкся. Спасибо )

@Hauts: спасибо )
Старый 31.10.2010 19:58 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
Для реализации реального MVC мало просто разделить всю логику на составляющие. Необходима поддержка парадигмы Notification -> Observer. Я не хочу здесь никого рекламировать. Пишу свою собственную надстройку над одним небезизвестным фреймоворком. Базовая Архитектура примерно следующая:

Stage mediator -> работает со stage. Умеет, руководствуясь собственной логикой добавлять и удалять Вьюшки на сцену.

Stage proxy -> хранит настройки stage mediator (неважно где, может хранить настройки по умолчанию а походу их менять, может записывать в shared object, может коммуницировать с сервером, либо тянуть настройки из xml зависит от типа выбраного прокси)

Далее целый комплекс view
Вьюшки разные, бывают статические, которые добавляются на сцену однажды при инициализации, никогда не удаляются и никак не меняются, например меню или простой бекграунд. Бывают динамические, которые добавляются по определенной логике.

Каждая вьюшка имеет свой медиатор и прокси по аналогии со sтаge. Вьюшки также могут быть простыми и составными. в простых есть только ссылка на конкретный displayobject, некое api для управления объектом, а также подписка на определенные события от объекта. Когда происходит что то серьезное, медиатор отправляет notification. В составных вью вложены другие простые вью. Я называю их viewComponent, которые тоже привязаны к собственным медиаторам и прокси.

Все общаются через notifications. Никто ничего не знает о своих соседях и потомках. вью не знает о том, что у нее есть медиатор, тупо отправляет события если что - то с ней случилось. Часть логики выполняется в медиаторе, если что - то серьезное: например нужно удалить со сцены текущую вью и добавить новую медиатор отправляет оповещение.

Это в двух словах. Далее я уже наворачиваю уникальные прокси для лучшего контроля над системой. Есть отдельный прокси по инициализации новых вью. Есть прокси, контролирующий оперативную память. Медиатор, прослушивающий глобалную клавиатуру и т п
Обновил(-а) inozemcev 31.10.2010 в 20:09
Старый 31.10.2010 20:21 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Даже в двух словах это звучит устрашающе
Для обучения сильно упрощенный и скомпилированный в голове пример Psycho Tiger лучше.
Старый 31.10.2010 21:08 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
Просто пугают возможно незнакомые слова прокси и медиаторы. Но на самом деле все достаточно просто. Прокси - часть программной логики, связанная с обработкой каких либо данных. Медиатор, часть программной логики связанная с визуальным объектом.

Далеко не всегда приходится писать уникальные прокси и медиаторы, часто можно обходится уже существующими, типовыми. В прокси просто необходимо зарегистрировать настройки, а в компоненте вью или самом вью если оно простое переопределить render функцию, которая отрисовывает изминившиеся настройки.

На высоком уровне я также реализовал состояния, ассоциативно связанные с вью.
Вот пример:

На сцене висит статическое вью 'меню' и допустим 'frontPage'. Пользователь нажал на раздел меню 'контакты'. Вьюшка 'меню' продиспачила событие 'на меня нажали' с каким то идентификатором типа string(пользовательское событие), например 'contacts'. Медиатор меню отловил событие, заблокировал меню и отравил оповещение 'состояние изменилось' с тем же идентификатором контакты.
Теперь медиатор, который работает со stage получил оповещение, 'состяние изменилось' и начал обрабатывать его. В моем простом примере он тупо пробижался по дисплей листу, удалил все что на нем нашлось (в данном случае frontPage) вытащил из массива вьюшек по айдишнику 'contacts' соответсвующую вью и поставил ее на сцену.

Все просто. Меню не знает ничего. о том что делать когда на нее нажали, кроме как отсылать соответсвующее событие. Медиатор не знает ничего о том, как отрисовано меню, хоть в 3D хоть кверху каком, хоть по русски хоть по американски. stage медиатор даже не подозревает, что в нем вложены какие - то меню. Он знает только, что в нем есть какие то displayObject одни из которых трогать нельзя а другие можно. (статические и динамические) Система привяза к состояниям, которые в свою очередь могут управляться и из вне непример через браузерную строку и swfadress. Только в этом случае, нужно сделать меню еще более тупым, чтобы оно даже активацию своих кнопок выполняло по команде!!
Старый 31.10.2010 21:59 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Вы, наверно, не с флешем работаете, ну или не с АС3
У нас обсервер реализован нативно, как раз с нотификациями типа String. (я об этом пару слов указал).

Прочитав Вас у меня возникло несколько вопросов:
1) Медиатор и Прокси не GoF`овские? Просто Ваше объяснение
Цитата:
Прокси - часть программной логики, связанная с обработкой каких либо данных. Медиатор, часть программной логики связанная с визуальным объектом.
как то вообще слабо граничит с тем, что делали GoF. Или Вы уже объяснили частность того, что стоит в Вашей программой за реализацией этих паттернов?

2) Я так понял StageMediator/Proxy это что то вроде главного контроллера... и контроллера вьюшки (???)? По сути если прокси - контроллер, то он заточен под что-то вроде адаптера - типа работаем с SharedObject/сервером/xml и т.д.?

3)
Цитата:
Каждая вьюшка имеет свой медиатор и прокси по аналогии со sтаge
Цитата:
Медиатор, часть программной логики связанная с визуальным объектом.
То есть на КАЖДУЮ вьюшку пишется медиатор? Если судить по Вашему описанию медиатора, мне совершенно не ясен этот ход. Если смотреть как на гофовский - далеко не каждой вьюшке нужен медиатор. Между контроллером и вьюшкой медиатор ставите?

4)
Цитата:
Часть логики выполняется в медиаторе
Не совсем уверен в правильности такого подхода. Под логикой подразумевается именно работа с данными?
Вообще по моим представлениям медиатор ставится чтобы устранить высокое сцепление объектов. На практике позволяет резко подменить вьюшку, что никто об этом не поймёт. Отсюда по моим представлением о какой-либо логике в медиаторе, по сути, речи быть не может.

5) По поводу разбора событий. Какой-то дисплей обджект выпустил событие, что нажали на меню, это поймал медиатор. Теперь медиатор это событие должен отбаблить до медиатора stage. Вопрос - как вы бабблите? В случае уровней вложенности большей двух (родитель и сын) каждое событие придётся редиспатчить, что не есть гуд - это ведь фреймворк, как никак. У Вас свой обсервер, или как Вы это делаете? Вопрос, конечно, актулаен если Вы со флешем работаете.
Обновил(-а) Psycho Tiger 31.10.2010 в 22:01
Старый 31.10.2010 22:16 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Цитата:
Медиатор и Прокси не GoF`овские?
Нет не их, его прокси и медиатор из терминологии PureMCV. Там система из трех синглтонов - Model, View, Controller. Медиаторы связывают отдельные предстовления и View, прокси связывают данные и Model, Controller служит для выполнения комманд.
Обсёрвер ГОФовский, он прослушивает события от пуремедиаторов и пурепрокси и либо выполняет комманды, либо говорит пуремедиаторам обновить их представления.

Ещё вся эта система инициализируется и управляется через Фасад. В общем для начала довольно сложно.
Обновил(-а) f.g.programmer 31.10.2010 в 22:19
Старый 31.10.2010 22:24 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Разве в PureMVC эти самые медиаторы и прокси не гофовские? Не знал. Пойду почитаю, спасибо.

P.S. PureMVC часто подвергается критике и весьма экстремистским высказываниям от достаточно авторитетных людей. Вы уверены что стоит брать его "за основу"?
Старый 31.10.2010 22:42 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Цитата:
Разве в PureMVC эти самые медиаторы и прокси не гофовские?
Хотя пожалуй я погорячился, идеологически они близки гофовским.
Старый 31.10.2010 23:09 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
Я работаю с actionscript.

У нас обсервер реализован нативно, как раз с нотификациями типа String. (я об этом пару слов указал).

Вообщем между событиями в actionscript и оповещениями есть разница. Суть именно в том, что события 'всплывают' наверх. А оповещения распространятся как бы это сказать 'горизонтально'. Допустим есть система из 15 наблюдателей, никакой иерархии зависимостей у них нет. Они ничего друг о друге не знают. Один обозреватель 'кричит' во все услышенье - 'со мной что - то случилось', и если другие обозреватели заитнересованы в этом (зарание подписались на оповещение) они отреагируют. Notification это не просто строка. Это внутренний объект в тело которого можно поместить все что угодно. Именно таким образом мой stage медиатор формирует свой лист из DisplayObject-s. Он просто получает соответствующее оповещение в теле которого есть ссылка на displayObject вьюшки и например ее id, ассоциированное с ее состоянием.

Я не знаю насколько pureMVC хороший фреймоврк по сравнению с остальными. Но мне он приглянулся именно благодаря notifications.

Теперь по поводу программной логики, в pureMC в можете хоть всю логику вынести за пределы прокси и медиаторов в простые и составные команды. pureMVC вас к этому и склоняет. Здесь уже я немного халтурю и оставляю логику в медиаторе, чтобы не плодить слишком простых команд. В команду я выношу какие -то важные этапы исполнения. Например команда InitUI - которая инициирует все вьюшки которые будут использоваться в проекте.

Я стараюсь чтобы именно у каждой вьюшки был свой собственный медиатор, таким образом получаю более лаконичный контроль над вьюшкой нежели если иметь один общий медиатор на все. но при этом несколько вьюшек могут иметь один общий прокси, в котором описаны общие для приложения настройки. Если хотите 'тему'. Например у всех вьюшек в вашей программе может быть один общий шрифт, или общий цвет беккраунда.
Обновил(-а) inozemcev 31.10.2010 в 23:11
Старый 01.11.2010 00:15 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
И еще pureMVC реализован на многих языках, так что можно писать и клиент и сервер, опираясь на общие парадигмы.
Старый 01.11.2010 00:51 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
inozemcev, у вас странные понятия о событиях. оповещения введены в оборот только по одно причине: они не нативные, а значит "языканезависимые". ( так говорит их автор - не я )
скажу по секрету: события в первую очередь распространяются горизонтально ( "как бы это сказать" - лишнее, именно так обычно и говорят ), просто ещё они умеют распространятся вертикально.
Старый 01.11.2010 01:31 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
вертикально они умеют распространятся только в том случае если объект включен в иерархию отображения. Причем как вы понимаете если объект, по каким то причинам пока что не добавлен в иерархию отображения, то он его и не получит. Предположим у меня есть три вьюшки с общими настройками, каждые двадцать секунд я меняю цвет фона в общем классе настроек и отправляю событие, но к сожалению не все мои вьюшки изменят свои настройки, потому что в displayList добавлена только одна из них. И теперь когда я удалю текущую вью и добавлю другую, то она вылезет с неодекватными цветами потому что она не услышала важного события.

Вторая проблема в том, что нужно отписываться от событий иначе как мы знаем объект останется в памяти, это конечно не столько проблема собственно событий, сколько garbageCollector - а, но от этого не легче. И как вы прикажете компоненту
отвязывать листенеров разбросанных по всему коду?!

Сильная зависимость классов не берется из неоткуда.

В случае с прокси или медатором, я просто удаляю медиатор, совершенно не заботясь о том, в каких оповещениях он был заинтересован.

Хотя формально вы конечно правы. Если реализовывать нативную событийную зависимость через диспетчеры а не через визуальные объекты, то они рассылаются горизонтально. Проблема только в том, что подписаться на такое событие, может только тот кто знает кто его рассылает.
Старый 01.11.2010 02:12 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Фактически, в пуре View играет роль глобального EventDispatcher-а. Он хранит массив всех слушателей, и при удалении конкретного медиатора происходит отписка.

Систему нотификаций в пуре можно совершенно безболезнено заменить на систему простых событий.
Обновил(-а) f.g.programmer 01.11.2010 в 02:14
Старый 01.11.2010 02:56 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
ну хорошо можно не спорю, pureMVC тоже написан на actionscript собственно, просто если вы перенимаете часть инструментария из pureMVC, почему бы не использовать сам фреймворк? Меня вот например совершенно не заботит как реализованы notifications главное что это удобно, вот и все. Мы ведь о практике MVC говорим, моя стратегия со стадже медиатором и вьюшками могла бы быть реализована без pureMVC, но зачем мне собственно изобретать велосипед ?
Старый 01.11.2010 11:16 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
inozemcev, причём здесь view? оповещения работаю точно так же. оповещения == события.
просто автор хотел сделать из пуре неведомую фигню и распространить на все языки мира, тем самым стать великим магистром тайного ордена. по итогу написать пару книжек: "pureMVC для чайников", "самоучитель: как заставить людей любить фигню на 3 дня". ну и переиздавать потом ещё раза 3.
Старый 01.11.2010 11:18 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
@All: можно уточнить, что есть горизонтальное и вертикальное всплытие событий? Из контекста понял, что вертикальное - это бабблинг, а горизонтальное - просто подписка на событие, имея ссылку. Если я прав, то не нативный бабблинг путём множественного редиспатча, по сути, горизонтальный (кругом по ссылке), каким он является?

Цитата:
Допустим есть система из 15 наблюдателей, никакой иерархии зависимостей у них нет. Они ничего друг о друге не знают. Один обозреватель 'кричит' во все услышенье - 'со мной что - то случилось', и если другие обозреватели заитнересованы в этом (зарание подписались на оповещение) они отреагируют
А что из этого нельзя сделать на нативном EventDispatcher`е?

Цитата:
Я не знаю насколько pureMVC хороший фреймоврк по сравнению с остальными. Но мне он приглянулся именно благодаря notifications.
Мне кажется это весьма сомнительный критерий для выбора архитектурного фреймворка. Но каждому своё, ничего против. )

Цитата:
Я стараюсь чтобы именно у каждой вьюшки был свой собственный медиатор, таким образом получаю более лаконичный контроль над вьюшкой нежели если иметь один общий медиатор на все.
Вам действительно это всегда нужно? Я не ощущаю неудобств в большинстве случаев, что моя вьюшка не содержит ни прокси, ни медиаторов (опять таки в контексте гоф).

Цитата:
Вторая проблема в том, что нужно отписываться от событий иначе как мы знаем объект останется в памяти, это конечно не столько проблема собственно событий, сколько garbageCollector - а, но от этого не легче. И как вы прикажете компоненту
отвязывать листенеров разбросанных по всему коду?!
Это... странно, чтоли. У Вас архитектура близкая к академической работе и возникают проблемы того, что Вы не знаете на что подписались?

Ещё странная проблема у вас с DO. Если DO нет в DisplayList`е, то оно не получает событий (???). Мне не очень понятно, с чего вообще её присутствие в дисплай листе на что-то влияет - команды он контроллера она всё равно получает, и события от модели - тоже.

Цитата:
Проблема только в том, что подписаться на такое событие, может только тот кто знает кто его рассылает.
А у Вас все подписываются у фиг-знает-кого на фиг-знает-что?
Старый 01.11.2010 11:47 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
не "всплытие", а "распространение".
Старый 01.11.2010 12:11 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Да, учту, спасибо. В остальном мои догадки по поводу распространении событий верны?
Старый 01.11.2010 12:37 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
Оповещения концептуально != события. Понятия близкие но не идентичные.

Цитата: 'А что из этого нельзя сделать на нативном EventDispatcher`е?'
- Не получится удалить листенер, просто удалив обозреватель.

Цитата:"Вам действительно это всегда нужно? Я не ощущаю неудобств в большинстве случаев, что моя вьюшка не содержит ни прокси, ни медиаторов (опять таки в контексте гоф)."

А кто слушает события вашей вьюшки, в этом случае? Просто если брать мою архитектуру, то вьюшка без медиатора просто не попадет на stage.
Старый 01.11.2010 12:41 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Цитата:
- Не получится удалить листенер, просто удалив обозреватель.
Обозреватель в контексте DO? REMOVED_FROM_STAGE с отпиской отовсюду, или просто метод destroy, который отпишет всё, что с ним связано.

Цитата:
А кто слушает события вашей вьюшки, в этом случае? Просто если брать мою архитектуру, то вьюшка без медиатора просто не попадет на stage.
Контроллер слушает.
Старый 01.11.2010 12:41 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
Мне не очень понятно, с чего вообще её присутствие в дисплай листе на что-то влияет - команды он контроллера она всё равно получает, и события от модели - тоже.

От какого такого контролера, мы же про нативные события говорим. Откуда он взялся в нативном actionscript ?
Старый 01.11.2010 12:42 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
О каких именно событиях речь?
Старый 01.11.2010 13:24 Hidest вне форума
Hidest
 
Аватар для Hidest
У контроллера есть ссылка на вьюху, которую он породил... Есть она в списке отображения, нет ли - все равно в ней что-то может происходить, и контроллер об этом узнает, так как она ему отдиспатчит вполне себе нативное событие.
Старый 01.11.2010 14:08 inozemcev вне форума
inozemcev
 
Аватар для inozemcev
Я начинаю немного путаться уже. Давайте просто определим цели использования MVC в проекте. А каким образом этого добиться, каждый будет выбирать сам.

Просто набор обязательных тезисов требований к архитектуре, чтобы быть точно уверенным в том, что 'сиськи есть' !
Старый 01.11.2010 14:41 BlooDHounD вне форума
BlooDHounD
 
Аватар для BlooDHounD
MVC без прокси, медиаторов и обсерверов - проще.
Старый 01.11.2010 16:05 Котяра вне форума
Котяра
 
Аватар для Котяра
pureMVC, плох тем что он просто есть)
MVC фрэймворк не нужен - нужно просто осознание mvc подхода.
Архитектуру проекта выстраиваем по mvc подходу, а не городим архитектуру вокруг какого нибудь pureMVC. Тяжело это и запутанно. Фасады, Мультитоны с Синглтонами.. Команды, Медиаторы и Прокси, Собственные Нотификаторы и Обсерверы...
А всего навсего надо Модель, Контроллер и Виды.
В pureMVC за деревьями не видно леса...
Я ещё согласен с мате с его глобальной картой событий и некоторым раздолбайством..
Но pureMVC - перебор. Честно пытался его использовать, но вышло себе дороже..
А вообще кроме MVC есть MVP, MV-VM, MV with IoC и ещё куча всяких буков)
Обновил(-а) Котяра 01.11.2010 в 18:46
Старый 01.11.2010 18:19 Котяра вне форума
Котяра
 
Аватар для Котяра
UPD
ковырялся тут в мате - клёвый метод:
Код AS3:
 //.........................................createInstance..........................................
                /**
                 * It is the actual creation method. It can throw errors if parameters are wrong.
                 */
                public function createInstance(template:Class, p:Array):Object
                {
                        var newInstance:Object;
                        if(!p || p.length == 0)
                        {
                                newInstance = new template();
 
                        }
                        else
                        {
                                // ugly way to call a constructor. 
                                // if someone knows a better way please let me know (nahuel at asfusion dot com).
                                switch(p.length)
                                {
                                        case 1: newInstance = new template(p[0]); break;
                                        case 2: newInstance = new template(p[0], p[1]); break;
                                        case 3: newInstance = new template(p[0], p[1], p[2]); break;
                                        case 4: newInstance = new template(p[0], p[1], p[2], p[3]); break;
                                        case 5: newInstance = new template(p[0], p[1], p[2], p[3], p[4]); break;
                                        case 6: newInstance = new template(p[0], p[1], p[2], p[3], p[4], p[5]); break;
                                        case 7: newInstance = new template(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); break;
                                        case 8: newInstance = new template(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); break;
                                        case 9: newInstance = new template(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); break;
                                        case 10:newInstance = new template(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]); break;
                                }
                        }
                        return newInstance;
                }
Старый 01.11.2010 18:59 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Хм, а действительно. call и apply как-то не применить. Какие есть другие способы?
Старый 01.11.2010 19:21 mayakwd вне форума
mayakwd
 
Аватар для mayakwd
нормальный метод. других вариантов нет.
Старый 02.11.2010 02:50 xpymbl4 вне форума
xpymbl4
 
Аватар для xpymbl4
Не сдержался. сохраняю эту ссылку на эту важную тему.
Старый 02.11.2010 09:29 f.g.programmer вне форума
f.g.programmer
 
Аватар для f.g.programmer
Цитата:
А вообще кроме MVC есть MVP, MV-VM, MV with IoC
По сути, всех их можно назвать разновидностями MVC.
Старый 02.11.2010 13:10 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Цитата:
Не сдержался. сохраняю эту ссылку на эту важную тему.
Не сдержались, простите, чего?
Пожалуйста. )

Цитата:
По сути, всех их можно назвать разновидностями MVC.
Ну, не совсем так. Из всех вообще мне именно MVC кажется наиболее удачным. Ну и всякие там M + VC, но по той же логике.
 

 


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


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