Я обычно не оставляю комментраии, но ты настолкько круто и просто объяснил этот паттерн и подобрал настолько хорошие приемры (лучше, чем В книге Паттерны Проектирования от HeadFirst ), что я это сделаю пож твоим роликом. Спасибо большое
Невероятно. Я - понял. Для меня декоратор был только звуком. Вроде звучит красиво, важно, но я его ни 🍆я не понимал... Отчаялся что я тупой, и к 40 заработал слабоумие... Блть. Огромное спасибо!! Для меня сейчас благодаря вам, в прямом смысле , истина открылась. Просветление. Сошлись пазлы. Декоратор, ОСП, высший класс, абстракция, полиморфизм, интерфейсы на нижних слоях, ООП... Матерь Божа.... Все как бы и где то знал, но обрывочно и бессвязно. И тут вы. Если бы не тяжёлое положение, задонатил бы в копилку. Но я подписался. У вас теперь надёжный последователь. ) дай бог времена изменятся..
Рад видеть Вас! Как всегда вовремя) Думаю, применить этот паттерн к модификации пушек в своём проекте (точность 20, а с рукояткой, глушителем становится 30, к примеру)
Самые лучшие примеры и объяснения. А ты знаешь канал git-amend? Можешь по подобному сценарию что-то снимать, я думаю это будет логичное продолжение твоих видео, но с большим количеством примеров
Привет. на 11:28 проговаривается, что класс DamageDecorator абстрактный (и по схеме UML так должно быть), но в коде же обычный класс ? Спасибо за отличные лекции по паттернам )
Здравствуйте, за недавнее время посмотрел почти все ваши видео по паттернам и мне очень понравилось как вы объясняете. Недавно делал свою игру и пришлось делать что похожее на смесь FSM и EventBus, в итоге наткнулся на паттерн Publish Subscribe Pattern, который очень был похож на то что у меня получилось, в итоге, и кторый почему то не упоминался во многих статьях, планируете ли вы сделать ролик по данному паттерну и правильно ли я понял его суть?
В любом случае, хотел сказать вам спасибо за ваши видео ролики, они максимально наглядные, и помогли мне многое осознать, желаю вам успехов в вашей карьере!☺
Слушай, а для юнити вообще важно качество кода, чтобы делать игры? То что ты объясняешь, помогает писать меньше кода, и это круто. Но есть много другого, чтобы оптимизировать свой код и сделать его читабельнее. С одной стороны не хочется быть ЯгдереДевом, а с другой не хочется потратить время на дрочку 0.00000001 секунды скорости запуска
Качество кода даёт гибкость, а значит в долгосрочной перспективе при добавлении новой фичи ты будешь меньше тратить на нее время. Вообще есть мнение, что чем жирнее и крупнее проект, тем выше должно быть качество кода. На конвейере гиперказуалок, где делают прототипы за три недели, требований к коду меньше. Но вообще мое мнение заключается в том, что хороший разраб может писать качественный код так же быстро, как некачественный. Потому что качественный код это простой/читаемый/удобно расширяемый а не супер умный и сложный код
Ну вообще то что ты написал про скорость запуска - это не про качество кода. Наоборот, чтобы код быстрее работал - он будет вынужден превратиться в месиво. А вообще качественный код, вопреки заблуждениям, это код простой и прямолинейный, который легко отлаживать и поддерживать. Усложнение кода это негативный момент. Чем проще код - тем проще с ним работать. Паттерны помогают писать простой код. Не все конечно, но в основном это так. Понятно дело, что писать кучу ифов и тд, когда можно упростить код и убрать дублирующиеся элементы - это необходимо. С яндере просто история о чрезмерном самомнении и нежелании стать лучше и узнать что-то. Ну и впринципе прямолинейный подход к написанию кода хорош, так как неявности создают сложность ради ничего. Некоторые стандартные решения тоже могут быть ненужными. Например, часто у юнити разрабов есть такое правило - писать приватное сериализуемое поле, но добавлять атрибут сериализации в инспекторе. В большинстве случаев это ничем не обусловлено и нет нужды делать так. И уж точно не надо делать так, а потом ещё геттер публичный - это контрпродуктивно. В реальности мы никогда не присваиваем в поля реюзаемых монобехов ничего. Отвечая на твой самый первый вопрос - качественный код нужен для того, чтобы процесс разработки был простым и не утомлял. Хорошее качество кода помогает тебе проще внедрить новые фичи, а не наоборот.
Не совсем понял, из-за чего этот паттерн считают как-то особняком от принципа наследования. Я понимаю, что "принципы" и "паттерны" - это разное, но всё же. Является ли "паттерн" декоратор чисто реализацией "принципа" наследования? И если да, зачем это было "паттерном" обзывать? Есть ещё способы реализации? Условно, есть класс Spell (не важно даже сейчас абстрактный или с базовой реализацией), от него можно унаследовать, например, FireBallSpell и FreezeSpell, у каждого свои свои доп.особенности в довесок к базовому функционалу (ну или свои конкретные реализации, если базовый класс абстрактный). И вот нам ещё понадобилось сделать критующие версии этих спеллов. Можно от каждого спелла унаследовать критверсию (но тут уже DRY косо поглядывает, полагаю), можно сделать доп.наследника базовому классу и от него унаследовать критверсии конкретных спеллов. Можно в базовом классе добавить поле для крита и вообще не делать доп.сущности, т.е. возможность критовать заложена изначально Является ли какой-то из примеров, собственно, примером обёртывания? Если нет, то как нужно переработать этот пример, чтобы таковым он стал? Просто я отличие декоратора от "простого наследника" увидел лишь в том, что у наследника есть поле типа класса-родителя, но зачем? Как будто в примерах в видео в этом нет необходимости - весь нужный базовый функционал и так передаётся по наследству при грамотной расстановке модификаторов доступа, разве нет?
1. Почему этот паттерн считают особняком от наследования. Разные паттерны используют принципы наследования. Абстрактная фабрика использует принцип наследования. Состояние использует принцип наследования. Декоратор тоже использует наследования. Но они все предназначены для разных задач и организованы чуть по разному. Паттерны это шаблонные решения шаблонных задач, а не чистые принципы 2. Является ли какой-то из этих примеров демонстрацией обёртывания. Нет, не является.Чтобы являлось, надо чтобы в spell был метод getDamage, затем создать декоратор critdamageDecorator который наследуется от spell.И вот когда вы напишете что-то типа var fireballWithCrit = new critdamageDecorator (fireBallSpell); вот тогда будет обёртывание
Хороший вопрос :) Для декораторов можно реализовать методы Unwrap или UnwrapAll. Тут конечно могут возникнуть небольшие трудности с тем чтобы отличить обёрнутый объект от необёрнутого, но всё же по аналогии обёртки можно сделать
Окей, паттерн декоратор - пушка, огонь, но как быть, когда мы хотим динамически добавлять объектам новую функциональность, с возможностью "отката до заводских настроек". Поясню на примере из видео с железным человеком. У нас есть клиент: Тони старк. Декораторы: Mark42 и его большой костюм. Мы добавили в SuperHero функционал Mark42 и функционал большого костюма при помощи декоратора, кажется что все супер, ведь SuperHero теперь может стрелять из лазера, выпускать ракеты при помощи логики большого костюма. Но допустим Тони стало жарко и он хочет снять костюм Mark42, НО оставить большой костюм. Как быть в таком случае? Учитывая то, что декораторов может быть сколько угодно, а нужно убрать конкретный. Получается в примере, который я описал выше, паттерн декоратор использовать не стоит? Но если не он, то кто из паттернов поможет сохранить OCP? Заранее спасибо за ответ
Тогда на моём личном опыте лучше сделать как в плохом примере, сделать массив модификаторов которые в итоге как-то суммируются. В случае когда мы убираем тот или иной костюм - просто удалять модификатор из массива. Сами в игре которую на работе пилили столкнулись ровно с той же проблемой и решили что массив чище и проще
Я не понял чем это отличается от обычного наследования типа [попугай : птица]. И зачем передавать объект класса если к нему и так, вроде, обратится можно через base
В обычном наследовании нет возможности слоями наращивать поведение и слоями их снимать. Попугай всегда останется попугаем. Декоратор же позволяет засунуть попугая в сову, а сову в орла и при полете у птицы будут и ночное видение совы, и клюв орла и окрас попугая)
Привет, такой вопрос. Насколько хороша идея, сделать небольшую игру(2-3 месяца разработки) и запихнуть туда все механики которые используют популярные паттерны и zenject? Такой пет проект будет отличным для демонстрации скилла для интервью или это сложно реализуемо?
Мне кажется- не получится. Паттернов много , в одну игру больше 5-7 впихнуть проблематично. Можно по аналогии с моим репозиторием(в закрепе patternDemoStorage) сделать индивидуальные сцены с механиками и на одном примере показать один паттерн
Зависит от того находится этот декоратор как самый внешний слой, или внутри. Если как самый внешний, то погуглите метод unwrap, в гите его нет но найти в интернете реально. Если декоратор зарыт где-то внутри, то я бы тогда советовал делать таки как в плохом примере, создать массив модификаторов и их суммировать
Да, декоратор не очень хорошо подходит под случаи постоянной смены набора модификаторов. Сам недавно писал систему статов, где на параметры влияет куча всего: предметы, ауры, премиум пропуск и решил отказаться от декоратора в пользу простого массива модификаторов
Ты умеешь в addressables ? Если конкретный ассет загрузить через addressables, загрузится только он или весь бандл, в котором он находится? Уже 2 сениора сказали что весь бандл Но мои тесты на голом проекте говорят четко об обратном. Я уже все перепроверил. У меня именно билд, именно 1 бандл. Всё четко
Декоратор использует И наследование и агрегацию. При наследовании мы наследуемся от базового класса (знак :). Если мы имеем ссылку на базовый объект, это значит что мы поместили базовый объект внутрь, то есть агрегация
Спасибо большое, но мне кажется книг по паттернам на рынке уже предостаточно. С другой стороны все мои материалы я записываю в одну доку, которая потихоньку становится справочником, там уже 55 страниц. Если оформить и напилить схемы, может получится вполне неплохая книжка, надо подумать :/
@@sergeykazantsev1655 не встречал изложение паттернов/ООП в контексте игр - хорошая наживка... Кстати, паттерн Посетитель будет? Кажется, один из самых полезных и трудных для понимания.
У вас дар объяснять сложное простыми словами. Спасибо за Ваш огромный труд, отдельно за конкретные примеры. Ваши видео самые лучшие! 🐝
Паттерн на примере железного человека, однозначно лайк )
Автор канала - человек с даром преподавания👀
Как всегда огромное спасибо! :)
За такое старательное объяснение на примере Железного Человека однозначно лайк и коммент!
Я обычно не оставляю комментраии, но ты настолкько круто и просто объяснил этот паттерн и подобрал настолько хорошие приемры (лучше, чем В книге Паттерны Проектирования от HeadFirst ), что я это сделаю пож твоим роликом. Спасибо большое
такие классные емкие и информативные видео, я надеюсь у вас все в порядке и выпуск новых эпизодов продолжится!
Спасибо большое) буду стараться
Я раньше смотрел видосы по декоратору, но понять его смог только сейчас. Спасибо
Невероятно. Я - понял. Для меня декоратор был только звуком. Вроде звучит красиво, важно, но я его ни 🍆я не понимал... Отчаялся что я тупой, и к 40 заработал слабоумие... Блть. Огромное спасибо!! Для меня сейчас благодаря вам, в прямом смысле , истина открылась. Просветление. Сошлись пазлы. Декоратор, ОСП, высший класс, абстракция, полиморфизм, интерфейсы на нижних слоях, ООП... Матерь Божа.... Все как бы и где то знал, но обрывочно и бессвязно. И тут вы. Если бы не тяжёлое положение, задонатил бы в копилку. Но я подписался. У вас теперь надёжный последователь. ) дай бог времена изменятся..
Аххрененеть, а я то думал, как накладывать разные эффекты друг на друга.
Спасибо, сударь. Ждем больше видосиков.
Очень понятно объясняешь + юмор, то что нужно.
Рад видеть Вас! Как всегда вовремя) Думаю, применить этот паттерн к модификации пушек в своём проекте (точность 20, а с рукояткой, глушителем становится 30, к примеру)
Спасибо! Если что-то интересное откроете при использовании, дайте знать)
Супер понятно объясняешь, спасибо за видео!
Просто лучшие ролики! Спасибо!
Отличная подача материала, спасибо!
Недавно повторял этот паттерн, но за мем с Гуррен-Лаганн - лайк
Как всегда шикарное объяснение )❤
Выглядит интересно, осталось начать понимать как и что делать в юнити)
Крутой видик, хотелось бы увидеть гайды по гиту в вашем исполнении :)
В идеи для новых видео запишу, но пока таких планов не было)
Сергей, спасибо за контент!
Как всегда кайф, ждем еще
Спасибо, очень хорошо объяснили.
Спасибо за уроки
Ееее новый паттерн 🥳
Отличный видос! Лайк
Спасибоооо!
Спасибо!
Самые лучшие примеры и объяснения. А ты знаешь канал git-amend? Можешь по подобному сценарию что-то снимать, я думаю это будет логичное продолжение твоих видео, но с большим количеством примеров
Вообще первый раз слышу, вчера ознакомился, надо будет подумать)
за наглядный пример с Тони - 5!
Привет.
на 11:28 проговаривается, что класс DamageDecorator абстрактный (и по схеме UML так должно быть), но в коде же обычный класс ?
Спасибо за отличные лекции по паттернам )
Да, должен быть абстрактным - очепятка с моей стороны - исправил, запушил)
Здравствуйте, за недавнее время посмотрел почти все ваши видео по паттернам и мне очень понравилось как вы объясняете. Недавно делал свою игру и пришлось делать что похожее на смесь FSM и EventBus, в итоге наткнулся на паттерн Publish Subscribe Pattern, который очень был похож на то что у меня получилось, в итоге, и кторый почему то не упоминался во многих статьях, планируете ли вы сделать ролик по данному паттерну и правильно ли я понял его суть?
В любом случае, хотел сказать вам спасибо за ваши видео ролики, они максимально наглядные, и помогли мне многое осознать, желаю вам успехов в вашей карьере!☺
Честно, о паттерне publish subscribe слышу впервые, очень похоже на Observer, по тому что вы сказали)
В любом случае спасибо за тёплые слова)
Слушай, а для юнити вообще важно качество кода, чтобы делать игры? То что ты объясняешь, помогает писать меньше кода, и это круто. Но есть много другого, чтобы оптимизировать свой код и сделать его читабельнее. С одной стороны не хочется быть ЯгдереДевом, а с другой не хочется потратить время на дрочку 0.00000001 секунды скорости запуска
Качество кода даёт гибкость, а значит в долгосрочной перспективе при добавлении новой фичи ты будешь меньше тратить на нее время.
Вообще есть мнение, что чем жирнее и крупнее проект, тем выше должно быть качество кода. На конвейере гиперказуалок, где делают прототипы за три недели, требований к коду меньше.
Но вообще мое мнение заключается в том, что хороший разраб может писать качественный код так же быстро, как некачественный. Потому что качественный код это простой/читаемый/удобно расширяемый а не супер умный и сложный код
Ну вообще то что ты написал про скорость запуска - это не про качество кода. Наоборот, чтобы код быстрее работал - он будет вынужден превратиться в месиво. А вообще качественный код, вопреки заблуждениям, это код простой и прямолинейный, который легко отлаживать и поддерживать. Усложнение кода это негативный момент. Чем проще код - тем проще с ним работать. Паттерны помогают писать простой код. Не все конечно, но в основном это так. Понятно дело, что писать кучу ифов и тд, когда можно упростить код и убрать дублирующиеся элементы - это необходимо. С яндере просто история о чрезмерном самомнении и нежелании стать лучше и узнать что-то.
Ну и впринципе прямолинейный подход к написанию кода хорош, так как неявности создают сложность ради ничего. Некоторые стандартные решения тоже могут быть ненужными. Например, часто у юнити разрабов есть такое правило - писать приватное сериализуемое поле, но добавлять атрибут сериализации в инспекторе. В большинстве случаев это ничем не обусловлено и нет нужды делать так. И уж точно не надо делать так, а потом ещё геттер публичный - это контрпродуктивно. В реальности мы никогда не присваиваем в поля реюзаемых монобехов ничего. Отвечая на твой самый первый вопрос - качественный код нужен для того, чтобы процесс разработки был простым и не утомлял. Хорошее качество кода помогает тебе проще внедрить новые фичи, а не наоборот.
Не совсем понял, из-за чего этот паттерн считают как-то особняком от принципа наследования. Я понимаю, что "принципы" и "паттерны" - это разное, но всё же. Является ли "паттерн" декоратор чисто реализацией "принципа" наследования? И если да, зачем это было "паттерном" обзывать? Есть ещё способы реализации?
Условно, есть класс Spell (не важно даже сейчас абстрактный или с базовой реализацией), от него можно унаследовать, например, FireBallSpell и FreezeSpell, у каждого свои свои доп.особенности в довесок к базовому функционалу (ну или свои конкретные реализации, если базовый класс абстрактный). И вот нам ещё понадобилось сделать критующие версии этих спеллов. Можно от каждого спелла унаследовать критверсию (но тут уже DRY косо поглядывает, полагаю), можно сделать доп.наследника базовому классу и от него унаследовать критверсии конкретных спеллов. Можно в базовом классе добавить поле для крита и вообще не делать доп.сущности, т.е. возможность критовать заложена изначально
Является ли какой-то из примеров, собственно, примером обёртывания? Если нет, то как нужно переработать этот пример, чтобы таковым он стал?
Просто я отличие декоратора от "простого наследника" увидел лишь в том, что у наследника есть поле типа класса-родителя, но зачем? Как будто в примерах в видео в этом нет необходимости - весь нужный базовый функционал и так передаётся по наследству при грамотной расстановке модификаторов доступа, разве нет?
1. Почему этот паттерн считают особняком от наследования. Разные паттерны используют принципы наследования. Абстрактная фабрика использует принцип наследования. Состояние использует принцип наследования. Декоратор тоже использует наследования. Но они все предназначены для разных задач и организованы чуть по разному. Паттерны это шаблонные решения шаблонных задач, а не чистые принципы
2. Является ли какой-то из этих примеров демонстрацией обёртывания. Нет, не является.Чтобы являлось, надо чтобы в spell был метод getDamage, затем создать декоратор critdamageDecorator который наследуется от spell.И вот когда вы напишете что-то типа var fireballWithCrit = new critdamageDecorator (fireBallSpell); вот тогда будет обёртывание
@sergeykazantsev1655 спасибо, кажется, понял!
Погодите-ка. А как убрать одну или несколько оберток? А как убрать все обертки? А? М?
Хороший вопрос :)
Для декораторов можно реализовать методы Unwrap или UnwrapAll. Тут конечно могут возникнуть небольшие трудности с тем чтобы отличить обёрнутый объект от необёрнутого, но всё же по аналогии обёртки можно сделать
Окей, паттерн декоратор - пушка, огонь, но как быть, когда мы хотим динамически добавлять объектам новую функциональность, с возможностью "отката до заводских настроек".
Поясню на примере из видео с железным человеком. У нас есть клиент: Тони старк. Декораторы: Mark42 и его большой костюм. Мы добавили в SuperHero функционал Mark42 и функционал большого костюма при помощи декоратора, кажется что все супер, ведь SuperHero теперь может стрелять из лазера, выпускать ракеты при помощи логики большого костюма. Но допустим Тони стало жарко и он хочет снять костюм Mark42, НО оставить большой костюм. Как быть в таком случае? Учитывая то, что декораторов может быть сколько угодно, а нужно убрать конкретный.
Получается в примере, который я описал выше, паттерн декоратор использовать не стоит? Но если не он, то кто из паттернов поможет сохранить OCP?
Заранее спасибо за ответ
Тогда на моём личном опыте лучше сделать как в плохом примере, сделать массив модификаторов которые в итоге как-то суммируются. В случае когда мы убираем тот или иной костюм - просто удалять модификатор из массива. Сами в игре которую на работе пилили столкнулись ровно с той же проблемой и решили что массив чище и проще
Я не понял чем это отличается от обычного наследования типа [попугай : птица]. И зачем передавать объект класса если к нему и так, вроде, обратится можно через base
В обычном наследовании нет возможности слоями наращивать поведение и слоями их снимать. Попугай всегда останется попугаем. Декоратор же позволяет засунуть попугая в сову, а сову в орла и при полете у птицы будут и ночное видение совы, и клюв орла и окрас попугая)
Привет, такой вопрос.
Насколько хороша идея, сделать небольшую игру(2-3 месяца разработки) и запихнуть туда все механики которые используют популярные паттерны и zenject? Такой пет проект будет отличным для демонстрации скилла для интервью или это сложно реализуемо?
Мне кажется- не получится. Паттернов много , в одну игру больше 5-7 впихнуть проблематично. Можно по аналогии с моим репозиторием(в закрепе patternDemoStorage) сделать индивидуальные сцены с механиками и на одном примере показать один паттерн
Если не секрет, какой прогой пользуешься для построения UML
Google slides :D
Как реализуется если надо убрать из всей цепочки один из декораторов?
Зависит от того находится этот декоратор как самый внешний слой, или внутри.
Если как самый внешний, то погуглите метод unwrap, в гите его нет но найти в интернете реально. Если декоратор зарыт где-то внутри, то я бы тогда советовал делать таки как в плохом примере, создать массив модификаторов и их суммировать
@@sergeykazantsev1655 да, например надо исключить его гдето в середине цепочки. получается стандартного общепринятого решения нет?
хотя наверно под приведеный пример с модификаторами урона в том случае когда модификаторы надо изменять или удалять это не про этот паттерн
Да, декоратор не очень хорошо подходит под случаи постоянной смены набора модификаторов. Сам недавно писал систему статов, где на параметры влияет куча всего: предметы, ауры, премиум пропуск и решил отказаться от декоратора в пользу простого массива модификаторов
Ты умеешь в addressables ?
Если конкретный ассет загрузить через addressables, загрузится только он или весь бандл, в котором он находится?
Уже 2 сениора сказали что весь бандл
Но мои тесты на голом проекте говорят четко об обратном. Я уже все перепроверил. У меня именно билд, именно 1 бандл. Всё четко
А какой тип сжатия бандла стоит? LZMA/LZ4/uncompressed? По идее от типа сжатия будет зависеть ответ
Привет, в чем существенная разница декоратора от наследования?
Привет, так вроде ответил на 03:14
@@sergeykazantsev1655 разве при наследовании мы не имеем ссылку на базовый объект через base?
Декоратор использует И наследование и агрегацию.
При наследовании мы наследуемся от базового класса (знак :). Если мы имеем ссылку на базовый объект, это значит что мы поместили базовый объект внутрь, то есть агрегация
Почему бы тебе не написать книгу. Я б купил. Как минимум бы скачал😊
Да да, точно точно. Вполне претендовать на самое уникальное изложение можно!
Спасибо большое, но мне кажется книг по паттернам на рынке уже предостаточно. С другой стороны все мои материалы я записываю в одну доку, которая потихоньку становится справочником, там уже 55 страниц. Если оформить и напилить схемы, может получится вполне неплохая книжка, надо подумать :/
@@sergeykazantsev1655 не встречал изложение паттернов/ООП в контексте игр - хорошая наживка... Кстати, паттерн Посетитель будет? Кажется, один из самых полезных и трудных для понимания.
В планах пока не было, так что если и будет, то не в ближайшее время
Огонь!🔥🔥🔥