|
|
|||||
Регистрация: Jul 2012
Сообщений: 44
|
ООП на практике
Всем привет. С теорией ООП я знаком, но опыта работы с этим делом пока не очень много. Хотелось бы понять некоторые принципы организации взаимодействия отдельных частей программы в больших проектах. Подскажите если можете или подкиньте статей. Буду благодарен всем ответам.
Вот к примеру у меня есть игра. В ней есть главный класс Game, класс с картой местности Map и класс Gui. Пример беру абстрактный (не из своего реального кода), просто чтобы смысл вопроса был понятен. 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(); } } Но как я понимаю такой принцип может породить проблемы. Слышал что такой код называется лапшой, когда все классы между собой очень сильно зависимы. Возникает вопрос: как правильно? Пока не придумал как сделать чтобы было и правильно и не сильно запутано. Есть только пара вариантов, в которых я не уверен: 1. Для таких случаев делать ф-ию в Game, в которой проверяется есть ли сейчас что-то в this.map и тогда уже вызывать this.map.showObject(); 2. Повесить кастомное событие на this.gui. В Gui когда надо вызывать это событие, которое Game примет и уже будет с ним делать что надо. Пока склоняюсь к версии с событиями. Но не уверен. Надеюсь, что опытные флешеры подскажут. |
|
|||||
Нуб нубам
модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
|
Не вижу противоречия "либо первое, либо второе", это как бы и не разные варианты одного и того же, а просто две разных фазы.
GUI посылает событие — ну, нормальное решение. Вместо него возможен только вариант "GUI напрямую вызывает функцию в Game", что конечно же и являлось бы характерным примером "жесткой связности", которую следует избегать. Вот насчет "кастомное событие" я не всегда согласен, ибо кастомное означает, что его должны знать, то есть импортировать в себя, оба класса, что так же создает связность и сложности с переносом в другой проект. Но это не так категорично плохо, как прямой вызов методов. У Вас Гейм является родителем для карты и интерфейса, он должен заниматься основной логикой. От ненужной логики его стоит разгружать. Упомянутый метод, который что-то там ищет в карте, не должен быть в Гейм, как мне кажется. Это ответственность Карты — она знает своих деток и она должна их считать, а не барневарн. Всегда надо проверять себя так: "если завтра я захочу перенести этот класс в другой похожий проект, придется ли мне писать 100500 строк для его интеграции и для его обслуживания в новом проекте?"
__________________
Reality.getBounds(this); |
|
|||||
Регистрация: Jul 2012
Сообщений: 44
|
Цитата:
|
|
|||||
Нуб нубам
модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
|
Так вот чтобы дети не обращались к родителям, их и учат посылать события.
Это в частности удаляет связность, ведь родитель не ОБЯЗАН обработать событие; он даже может на него не подписываться, это его личное дело. Вы же не подписываетесь на ВСЕ события, которые умеет генерить Спрайт)) Спрайт и ваши кастомные классы — яркий пример хорошего разделения, абстрагирования классов. Спрайт не пытается вызывать какие-то методы у ваших классов? Именно поэтому Вы можете лепить из спрайтов любой проект. Он переносимый. Потому что ни от кого ничего не требует для своего комфорта и информирует всех, кому это интересно, о своих событиях.
__________________
Reality.getBounds(this); |
|
|||||
Banned
[+4 24.02.14]
[+4 07.11.13] [+ 13.03.14] Регистрация: Mar 2013
Сообщений: 1,864
|
Цитата:
Они очень интересные, но если честно, после прочтения, хочется читать ещё, но уже нечего. И пользуясь случаем, немного оффтопа - если кто-то видел пример паттерна репозиторий на as3, дайте ссылку. |
|
|||||
Регистрация: Jul 2012
Сообщений: 44
|
На счет переносимости классов я понял. Очень доходчиво объяснили, за это спасибо. Я в общем-то по этому и задумался над этой всей темой. Но с событиями не понял один момент. Почему нежелательно использование кастомных событий. Под ними я имею в виду свои классы событий которые наследуются от Event. Вот пример: Пользователь нажал на кнопку. Кнопка была создана в классе Gui. Получается что обработчик события click находится в Gui. Теперь нужно сообщить остальной части программы что случилось. Для этого есть к примеру класс GuiEvent. В Gui делаю dispatchEvent(GuiEvent.ButtonUsed).
В Game вешаю слушатель этого события, чтобы в нужный момент вызвать что-то в классе Map. Вот и получается что никакие классы не работают со своими родителями. Этот вариант мне симпатичен. Но наверное тогда получится много кода в Game. По событию на каждое действие в Gui которое влечет за собой действие в Map. Хотя может это и правильно. Добавлено через 6 минут За литературу спасибо тоже ) Добавлено через 35 минут Хотелось бы еще узнать ваше мнение на счет одного способа взаимодействия классов. Например у меня есть класс который представляет из себя окно. В окне можно выбрать предмет из списка. Я могу в конструктор этого класса-окна передать функцию callBack. И когда объект будет выбран - будет вызвана эта функция. Тот же метод я хочу применить в классе загрузщика файлов. Будет ли это хорошим кодом? |
|
|||||
Нуб нубам
модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
|
Цитата:
__________________
Reality.getBounds(this); |
|
|||||
Banned
[+4 24.02.14]
[+4 07.11.13] [+ 13.03.14] Регистрация: Mar 2013
Сообщений: 1,864
|
Как-то давно, мне объясняли про события, попробую пересказать ( но объясняю я плохо ).
Предположим, Вы пишете собственные классы - кнопки, скроллы, выпадающие списки, которые на столько взаимосвязанные, что из набора классов, получается целый модуль, который называется компоненты. Так-вот, многие классы в этом модуле общаются друг сдругом при помощи событий и сделать для них собственное событие ComponentsEvent будет считаться нормально. Не знаю, правильно ли подобрано слово "нормально", но посудите сами, где бы Вы не использовали эти компоненты, нужен весь модуль и плюс ко всему, кастомное событие ComponentsEvent работает только внутри модуля. Пользователь об этом событии не чего не знает. Но представим, что нужно, чтобы какой-то компонент слал событие из модуля наружу. Если это тоже будет кастомное событие, то его придется пользователю импортировать. А это уже является как бы связанностью. Вместо этого, можно поступить немного иначе - создать отдельный класс констант с красивым именем ( фасад, если не ошибаюсь ) - package { public class EventOfComponentsOut { public static const EXECUTE:String = "execute"; } } // подписываемся на событие используя родное событие Event addEventListener(EventOfComponentsOut.EXECUTE, executeHandler); // посылаем событие используя родное событие Event dispatchEvent(new Event(EventOfComponentsOut.EXECUTE)); private function executeHandler(event:Event):void { } которое нужно применять так, как я показал выше, только вместо Event писать DataEvent. И спасибо Wolsh'у |
|
|||||
Нуб нубам
модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
|
Попросту, если есть возможность использовать обычный Event и DataEvent, нет смысла городить наследников. В большинстве случаев Вам не надо передавать кучу данных с событием. В случае с Gui тем более — никаких координат, всегда можно обойтись просто строковым типом объекта класса Event. Даже в случае с данными, например уровень громкости и т.п., можно использовать стандартный DataEvent, хотя там и некрасиво получается перевод числа в строку и обратно. Зато эти классы стандартные, их не получится забыть, потерять или неожиданно изменить.
__________________
Reality.getBounds(this); |
|
|||||
Регистрация: Jul 2012
Сообщений: 44
|
Все понятно. Всем спасибо
|
Часовой пояс GMT +4, время: 01:16. |
|
« Предыдущая тема | Следующая тема » |
|
|