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

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 05.04.2014, 15:37
darkthor вне форума Посмотреть профиль Отправить личное сообщение для darkthor Найти все сообщения от darkthor
  № 1  
Ответить с цитированием
darkthor
 
Аватар для darkthor

Регистрация: Jul 2012
Сообщений: 44
По умолчанию ООП на практике

Всем привет. С теорией ООП я знаком, но опыта работы с этим делом пока не очень много. Хотелось бы понять некоторые принципы организации взаимодействия отдельных частей программы в больших проектах. Подскажите если можете или подкиньте статей. Буду благодарен всем ответам.

Вот к примеру у меня есть игра. В ней есть главный класс Game, класс с картой местности Map и класс Gui. Пример беру абстрактный (не из своего реального кода), просто чтобы смысл вопроса был понятен.
Код AS3:
public class Game extends Sprite 
{
    public static var instans:Game;
    public var map:Map;
    public var gui:Gui;
 
    public function Game(stage:Stage) 
    {
        Game.instans = this;
 
        this.map = new Map();
        this.gui = new Gui();
    }
}
И вот например игрок нажал на кнопку в gui и нужно на карте показать какой-то объект. Самый простой способ это сделать это поставить в классе Gui такой вызов:
Код AS3:
Game.map.showObject();
Но как я понимаю такой принцип может породить проблемы. Слышал что такой код называется лапшой, когда все классы между собой очень сильно зависимы. Возникает вопрос: как правильно?

Пока не придумал как сделать чтобы было и правильно и не сильно запутано. Есть только пара вариантов, в которых я не уверен:
1. Для таких случаев делать ф-ию в Game, в которой проверяется есть ли сейчас что-то в this.map и тогда уже вызывать this.map.showObject();
2. Повесить кастомное событие на this.gui. В Gui когда надо вызывать это событие, которое Game примет и уже будет с ним делать что надо.

Пока склоняюсь к версии с событиями. Но не уверен. Надеюсь, что опытные флешеры подскажут.

Старый 05.04.2014, 17:07
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 2  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Не вижу противоречия "либо первое, либо второе", это как бы и не разные варианты одного и того же, а просто две разных фазы.
GUI посылает событие — ну, нормальное решение. Вместо него возможен только вариант "GUI напрямую вызывает функцию в Game", что конечно же и являлось бы характерным примером "жесткой связности", которую следует избегать. Вот насчет "кастомное событие" я не всегда согласен, ибо кастомное означает, что его должны знать, то есть импортировать в себя, оба класса, что так же создает связность и сложности с переносом в другой проект. Но это не так категорично плохо, как прямой вызов методов.
У Вас Гейм является родителем для карты и интерфейса, он должен заниматься основной логикой. От ненужной логики его стоит разгружать. Упомянутый метод, который что-то там ищет в карте, не должен быть в Гейм, как мне кажется. Это ответственность Карты — она знает своих деток и она должна их считать, а не барневарн. Всегда надо проверять себя так: "если завтра я захочу перенести этот класс в другой похожий проект, придется ли мне писать 100500 строк для его интеграции и для его обслуживания в новом проекте?"
__________________
Reality.getBounds(this);

Старый 05.04.2014, 17:56
darkthor вне форума Посмотреть профиль Отправить личное сообщение для darkthor Найти все сообщения от darkthor
  № 3  
Ответить с цитированием
darkthor
 
Аватар для darkthor

Регистрация: Jul 2012
Сообщений: 44
Цитата:
GUI посылает событие — ну, нормальное решение.
Не совсем понял что именно имеется в виду. Ведь чтобы передать что-то в Game нужно обратится к нему через Game.instans.blabla();

Старый 05.04.2014, 18:11
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 4  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Так вот чтобы дети не обращались к родителям, их и учат посылать события.
Это в частности удаляет связность, ведь родитель не ОБЯЗАН обработать событие; он даже может на него не подписываться, это его личное дело. Вы же не подписываетесь на ВСЕ события, которые умеет генерить Спрайт)) Спрайт и ваши кастомные классы — яркий пример хорошего разделения, абстрагирования классов. Спрайт не пытается вызывать какие-то методы у ваших классов? Именно поэтому Вы можете лепить из спрайтов любой проект. Он переносимый. Потому что ни от кого ничего не требует для своего комфорта и информирует всех, кому это интересно, о своих событиях.
__________________
Reality.getBounds(this);

Старый 05.04.2014, 19:02
Akopalipsis вне форума Посмотреть профиль Найти все сообщения от Akopalipsis
  № 5  
Ответить с цитированием
Akopalipsis
Banned
[+4 24.02.14]
[+4 07.11.13]
[+ 13.03.14]

Регистрация: Mar 2013
Сообщений: 1,864
Цитата:
Не совсем понял что именно имеется в виду. Ведь чтобы передать что-то в Game нужно обратится к нему через Game.instans.blabla();
Так не нужно, Вы же и так создали экземпляры гуи в гейме.Теперь все что нужно, это подписать на событие эти самые гуи и когда пользователь нажмет на кнопку, то гейм поймает событие и примет решение, что нужно сейчас показать. И раз Вы дошли до момента, когда при написании приложений, в голове эхом отдаются слова - логика и правильно, то можете почитать книги, которые указаны в моей подписи.
Они очень интересные, но если честно, после прочтения, хочется читать ещё, но уже нечего.

И пользуясь случаем, немного оффтопа - если кто-то видел пример паттерна репозиторий на as3, дайте ссылку.

Старый 07.04.2014, 00:30
darkthor вне форума Посмотреть профиль Отправить личное сообщение для darkthor Найти все сообщения от darkthor
  № 6  
Ответить с цитированием
darkthor
 
Аватар для darkthor

Регистрация: Jul 2012
Сообщений: 44
На счет переносимости классов я понял. Очень доходчиво объяснили, за это спасибо. Я в общем-то по этому и задумался над этой всей темой. Но с событиями не понял один момент. Почему нежелательно использование кастомных событий. Под ними я имею в виду свои классы событий которые наследуются от Event. Вот пример: Пользователь нажал на кнопку. Кнопка была создана в классе Gui. Получается что обработчик события click находится в Gui. Теперь нужно сообщить остальной части программы что случилось. Для этого есть к примеру класс GuiEvent. В Gui делаю dispatchEvent(GuiEvent.ButtonUsed).
В Game вешаю слушатель этого события, чтобы в нужный момент вызвать что-то в классе Map.
Вот и получается что никакие классы не работают со своими родителями. Этот вариант мне симпатичен. Но наверное тогда получится много кода в Game. По событию на каждое действие в Gui которое влечет за собой действие в Map. Хотя может это и правильно.

Добавлено через 6 минут
За литературу спасибо тоже )

Добавлено через 35 минут
Хотелось бы еще узнать ваше мнение на счет одного способа взаимодействия классов. Например у меня есть класс который представляет из себя окно. В окне можно выбрать предмет из списка. Я могу в конструктор этого класса-окна передать функцию callBack. И когда объект будет выбран - будет вызвана эта функция.
Тот же метод я хочу применить в классе загрузщика файлов. Будет ли это хорошим кодом?

Старый 07.04.2014, 01:08
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 7  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Цитата:
Но с событиями не понял один момент. Почему нежелательно использование кастомных событий.
Я уже сказал, что это на самом деле не так важно и нет особого смысла вылизывать все до перфекшена. Неидеальность здесь в том, что и класс Gui и класс Game зависят от класса GuiEvent. Соответственно, если Вам захочется перенести класс Gui в другой проект, этот проект должен так же знать GuiEvent, фернштейн? И наоборот, чтобы заменить класс Gui на другой, Вы должны обеспечить чтобы этот другой посылал события именно класса GuiEvent. Не то чтобы это смертельно, ведь не так уж часто переносят такие классы по проектам. Тем не менее, это связность через "третье лицо". Сейчас понятней?
__________________
Reality.getBounds(this);

Старый 07.04.2014, 01:08
Akopalipsis вне форума Посмотреть профиль Найти все сообщения от Akopalipsis
  № 8  
Ответить с цитированием
Akopalipsis
Banned
[+4 24.02.14]
[+4 07.11.13]
[+ 13.03.14]

Регистрация: Mar 2013
Сообщений: 1,864
Как-то давно, мне объясняли про события, попробую пересказать ( но объясняю я плохо ).
Предположим, Вы пишете собственные классы - кнопки, скроллы, выпадающие списки, которые на столько взаимосвязанные, что из набора классов, получается целый модуль, который называется компоненты.
Так-вот, многие классы в этом модуле общаются друг сдругом при помощи событий и сделать для них собственное событие ComponentsEvent будет считаться нормально. Не знаю, правильно ли подобрано слово "нормально", но посудите сами, где бы Вы не использовали эти компоненты, нужен весь модуль и плюс ко всему, кастомное событие ComponentsEvent работает только внутри модуля. Пользователь об этом событии не чего не знает.
Но представим, что нужно, чтобы какой-то компонент слал событие из модуля наружу. Если это тоже будет кастомное событие, то его придется пользователю импортировать. А это уже является как бы связанностью. Вместо этого, можно поступить немного иначе -
создать отдельный класс констант с красивым именем ( фасад, если не ошибаюсь ) -
Код AS3:
package 
{
	public class EventOfComponentsOut 
	{
		public static const EXECUTE:String = "execute";
	}
}
Всё, красивое и индивидуальное названия события мы получили и для его применения не нужно импортировать собственное событие. А использовать его вот как -
Код AS3:
// подписываемся на событие используя родное событие Event
addEventListener(EventOfComponentsOut.EXECUTE, executeHandler);
 
// посылаем событие используя родное событие Event
dispatchEvent(new Event(EventOfComponentsOut.EXECUTE));
 
private function executeHandler(event:Event):void 
{
 
}
Но тут есть одно но, если вам нужно передать объект вместе с событием, то придется переопределять класс Event и добавлять туда нужный параметр. Но если Вам нужно передать вместе с событием строку, например значение какой-то константы или ещё чего-то, то у флеша для этого есть тоже родное событие - DataEvent,
которое нужно применять так, как я показал выше, только вместо Event писать DataEvent.
И спасибо Wolsh

Старый 07.04.2014, 01:18
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 9  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Попросту, если есть возможность использовать обычный Event и DataEvent, нет смысла городить наследников. В большинстве случаев Вам не надо передавать кучу данных с событием. В случае с Gui тем более — никаких координат, всегда можно обойтись просто строковым типом объекта класса Event. Даже в случае с данными, например уровень громкости и т.п., можно использовать стандартный DataEvent, хотя там и некрасиво получается перевод числа в строку и обратно. Зато эти классы стандартные, их не получится забыть, потерять или неожиданно изменить.
__________________
Reality.getBounds(this);

Старый 07.04.2014, 01:34
darkthor вне форума Посмотреть профиль Отправить личное сообщение для darkthor Найти все сообщения от darkthor
  № 10  
Ответить с цитированием
darkthor
 
Аватар для darkthor

Регистрация: Jul 2012
Сообщений: 44
Все понятно. Всем спасибо

Создать новую тему Ответ Часовой пояс GMT +4, время: 21:19.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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