начал писать консольную игру "саймон говорит" с простыми заданиями чисто для практики, типа верх право прыжок и задумался над расширением команд. нашел ваше видео. это самый быстрый и доходчивый вьезд в паттерн получился. Спасибо!
Спасибо! Рассказываешь лучше, чем лицензированный Майкрософт чел из МТС, который половину выдаёт на платных курсах, а бесплатными видео только заманивает. Объяснения лучшие, пример отличный)
Очень жду новых видео роликов от Вас... И сдаётся мне такое ощущение, что их уже не будет. Очень печально. =( Вы бы хоть причину назвали, почему решили бросить. У вас видео получается на уровне между "шедевр" и "божественно!"
Манера изложения автора не оставляет мне шансов быть недоучкой по С# , спасибо автор, снимаю шляпу перед вашим талантом гипнотического воздействия на способность сконцентрировать все ресурсы мозга на впитывание материала
Благодарю! По спонсорству, там пока не хватает необходимого количества часов просмотров. Как наберется, можно будет включить. Идея с мерчом интересная, подумаю об этом :)
Хорошее видео, всё понятно. Но маленький нюанс, можно сделать размер шрифта в IDE в будущих видео чуть больше? На слайдах код прекрасно видно, а вот в IDE я его на слух восстанавливаю. А сидеть сильно близко к телевизору, чтобы всё увидеть, неудобно.
Первое что приходит в голову у новичка - создать класс пухи с различными характеристиками, задавать поведение через конструктор её экземплярам и передавать их уже в целевой класс. Возможно ты пользовался этим подходом? Интерфейсы начинаешь применять когда у объектов совсем уж разная логика, например красная бочка и враг, ну или для всяких кнопок
Мне кажется, что лучше здесь подошёл абстрактный класс, ибо тут строится логика из однотопных объектов - оружий. Интерфейсы больше подходят для тех классов, которые между собой вообще ничем не схожи, то есть выполняют совсем иные действия . Например, интерфейс лучше для такого типа действий: у нас ечть дерево, персонаж и оружие, всё эти объекты совсем разные и мх связать наследованием не получится, тут абстрактный класс не подойдёт, подойдёт интерфейс, например мы зотим, чтобы все эти объекты получали урон, мы просто срздаем интерфейс IDamageble в которм будет метод TakeDamage, и теперь у нас есть уровень абстракции для всех объектов, коиорые могут получать урон, конечно, реализация этих мктово модет быть разной.
Почему такие авторы, как Codaza, Simple Code перестают выпускать видео?! Только появляется надежда, что я пойду все темы в программировании и баац они исчезают из ютуба( Да, понимаю запись новых роликов занимает очень много времени, учитывая ваш щепетильный подход ко всем деталям, но со временем это, наверное, можно было бы как-то масштабировать и выйти на существенный доход...
А как в очередной реализации стратегии мы можем обратиться к свойствам контекста-сквидварда. А то тогда не понятно зачем это все. Что если в реализации орудия умерщвления, нам нужно менять состояние контекста, например сквидвард задержал гранату в руке и она взорвалась и теперь он должен получить урон? А то они будто все в воздухе подвешены и ни к чему не привязаны. Это сильно ограничивает возможности реализации.
Все понятно, доступно, круто и т.д., но у меня вопрос. мы вот это все реализовали, но как это нормально дергать и дать фронтам на растерзание я не понимаю. Ты в Main передаешь конкретные имплементации, но что если мы напишем апи, где параметр будет как раз одно из значений энамки с видео (WaterGun, Plumber, Broom), а мы уже в зависимости от этого параметра должны установить в метод SetWeapon конкретную реализацию интерфейса. У меня в голове все сводится опять же к switch который нарушает вторый принцип SOLID. Типо: IWeapon weapon = gunType switch { WaterGun => new WaterGun(), Plumber => new Plumber(), Broom => new Broom() }; hero.SetWeapon(weapon); ... Опять все это придется каждый раз модифицировать при появлении нового значения в энамке. Это можно как то обойти?
Иван, если у Вас есть необходимость избавиться от switch и enum, то можно: 1. Предоставить в API отдельные endpoint-ы под каждый вид оружия. 2. Пробрасывать вызовы, используя паттерн CQRS, на конкретные имплементации обработчиков (handlers). Роутинг можно обеспечить по атрибутам.
Привет 👋 Это означает, что мы даём явное указание на то, что переменная может принимать значение null. Если в свойствах проекта Visual Studio 2022, отключить настройку Nullable Context, то, для ссылочных типов, знак вопроса можно не указывать.
Нет, это будет слишком общее определение. Интерфейсы используются по назначению в самых разных ситуациях, выходящих далеко за рамки паттерна Strategy. Если вы хотите услышать суть паттерна одной фразой, то это скорее будет звучать так: выделение схожих алгоритмов с возможностью их использования в объектах, при помощи интерфейсов.
Введение абстрактного класса имеет смысл, когда у нас есть некоторый базовый функционал, который переиспользуется в наследниках. В примере, который мы рассматриваем в видео, производится простой вывод на консоль. На мой взгляд, введение дополнительного слоя абстракции внесло бы избыточную сложность, которая не нужна для понимания механики паттерна Strategy. В рельных проектах, где Weapon имеет общую логику, абстрактный класс была бы весьма кстати. Так что вы верно уловили суть 🙂
Спасибо! У меня есть вопрос. Изначально было сказано, что метод Attack принимает параметр GunType, почему бы не задать IWeapon в качестве параметра для метода Attack, а создать метод SetWeapon? Это какое-то правило?
@@dilshodkomilov9121 В ролике я показал классический вариант паттерна Strategy, который предполагает указание стратегии отдельно от выполнения операции. Вариант с указанием стратегии при вызове операции так же является допустимым. Здесь нет строгих рамок.
@@aaa_aaa6226 Так можно сделать если ваш герой должен быть без оружия или с одним видом оружия на протяжении всей игры. Не думаю что это актуальная логика для игры, но если вам нужно именно такое поведение, то можно так 🙂
Видео как всегда на высоте, но есть и вопросы. По сути, это же можно реализовать через полиморфизм и тут вопрос, это сам паттерн такой, что позволяет делать выбор в ту или иную сторону или же просто пример так совпал?
Через полиморфизм будет другой паттерн - Visitor (посетитель). Смысл паттерна убрать жесткую зависимость между классом использующим оружие и его поведением. Мы типо написали абстракцию, что хотим, чтобы героя атаковал, а как, чем, это ему не известно
Всё понятно, но есть важный вопрос! Если нам нужно не просто запустить метод Attack(), но и передать в него какие-то параметры при запуске. Для пистолета - 1 параметр, для вантуза - 2 параметра, а для веника - никаких параметров передаваться не нужно. То как реализовать такое? Ведь это должно указываться непосредственно в классах оружия, а не в самом интерфейсе. Но в таком случае запустить эти методы не получится, т.к. в самом интерфейсе их не будет, к тому же сигнатуры этих методов будут отличаться от сигнатур интерфейса. В общем, это работать не будет. Можно, конечно, указать в интерфейсе все необходимые сигнатуры методов. Но тогда все этих сигнатуры будет нужно реализовать во всех классах оружия. А нам для каждого класса нужен только один метод атаки, но просто принимающий определённые параметры. Надеюсь, мои рассуждения не слишком запутаны. Т.е. вопрос по сути такой: что делать, если нам нужно, чтобы для метода Attack() у каждого оружия была разная сигнатура (принимаемые аргументы)? Заранее благодарю за ответ!
@@bamblebi1773 А как мне ПЕРЕДАТЬ в этот класс параметры? Если у разных классов - разные параметры. Перечитайте ещё раз то, о чём я спросил в комментарии, на который вы ответили. Суть именно в передаче аргументов. Если у вас есть ответ на этот вопрос - буду признателен.
@@aleksey8405 У разного оружия могут быть разные параметры/настройки, поэтому при описании класса с конкретным оружием необходимо добавить поля для этих параметров. Дальше в конструкторе передавать эти параметры при создании экземпляра конкретного оружия, либо через свойства. Далее, в методе Attack конкретного оружия, вы можете использовать эти параметры.
@@bamblebi1773 Использовать свойства? Нельзя обратиться через тип данных интерфейса к свойствам, которые не указаны в самом интерфейсе. Метод Attack может быть разным для каждого класса, но его сигнатура - должна быть одинаковой для всех. Вы не можете для одного из классов сделать сигнатуру, принимающую, например int и string. А для другого - только int. А для третьего - вообще ничего не принимающую. Этот метод должен быть одинаковым для всех, иначе код не скомпилируется. Это принцип работы интерфейсов. И программа ничего не знает о тех параметрах, которые вы добавили дополнительно в какой-то из классов. Потому что они не указаны в интерфейсе. Вы не сможете обратиться к ним через тип данных интерфейса. Вы не можете передать никаких аргументов, уникальных для каждого класса. Только общие, заданные в интерфейсе. И здесь нужно либо использовать привидение типов, например. Но это плохая практика. Понимаете, о чём я?
@@aleksey8405 Извините, я неправильно написал где использовать эти параметры. Не в методе Attack, а в методе Shoot конкретного оружия. А при создании оружия, создавать его с необходимыми параметрами. Таким образом, каждое оружие будет обладать своими параметрами, и исходя из этих параметров будет реализован метод Shoot.
@@xinitru в моем понимании, паттерн - это комбинация из нескольких приемов. Может я не прав, не претендую на истину в последней инстанции. Ну по сути любой паттерн - это набор простейших понятий и приемов. Такие легкие понятия, как наследование, агрегирование, композиция и т.д., объединяются в какую-то более сложную схему, которая и называется паттерном.
@@phat80 Ну Интернет с Вами не согласен: Design patterns are typical solutions to commonly occurring problems in software design. И Dependency Injection практически везде называют паттерном. На самом деле, я нашел ответ о различиях. Стратегия применяется для случаев, когда классу необходимо определить разнообразные меняющиеся на протяжении его жизненного цикла действия. А Внедрение Зависимостей обычно применяется для однократного определения реализации поведения в начале жизненного цикла объекта, не меняющегося до его уничтожения. Например, в видео, Сквидвард то вантузом атакует, то бумерангом, то еще чем-то. При использовании Внедрения Зависимостей, мы бы еще в начале жизни задали ему конкретный способ атаки, и дальше он бы атаковал только так.
@@xinitru ну не согласен, так не согласен. Такое впечатление, что вы задали кому-то вопрос именно с целью написать, что интернет с этим кем-то не согласен 😂 Доказывать свою правоту не буду, так как не имею на это право, ибо сам в ООП имею только какие-то базовые знания и вероятно неправильные, как выясняется.
Обязательно ли использовать интерфейс? Можно ведь использовать абстрактный класс вместо интерфейса в котором будет своя какая-то реализация: abstract class Weapon { public abstract string WeaponName { get; } public abstract int Damage { get; } public void Shoot(string nickname) { Console.WriteLine($"{nickname} атаковал используя {WeaponName} и нанёс {Damage} DMG!"); } } class Bow : Weapon { public override string WeaponName => "Лук"; public override int Damage => 12; } // Действия в классе Hero точно такие же как в видео, просто меняем IWeapon на мой класс Weapon Будет ли это реализацией стратегии? Если честно мне кажется, что я не до конца понимаю когда надо использовать интерфейс, а когда абстр. класс. Заранее спасибо большое за ответ! Надеюсь понятно объяснил свой вопрос
Как то принято через интерфейсы все паттерны делать, но абстрактный класс так же можно использовать - что абстрактный класс, что интерфейс являются абстракцией, на базе чего и строится смысл паттерна
В теории все понятно. Но на практике - полнейший туман. Раз уж упоминаются игры, то вспоминается Unity. Но какие там могут быть new при объединении интерфейсов вместе с MonoBehavior?.. Да никаких. Получается, что все эти дополнительные сущности - обычные костыли к MonoBehavior и префабам. Ничего они не упрощают по большому счету. Но в консоли красиво смотрится )
К сожалению, я не работаю с Unity, поэтому не смогу прокомментировать этот момент. Однако не списывайте паттерн Strategy со счетов, так как это не паттерн плохой, а скорее мне не удалось донести до вас его суть в понятном для вас ключе. Могу лишь добавить, что с точки зрения backend разработки, этот паттерн является одним из часто используемых, так как позволяет расширять логику классов без их модификации. Даже, с точки зрения десктопных приложений (например, Photoshop), как добавить какой-нибудь плагин? Плагину нужно реализовать интерфейс и далее его можно добавить в основную логику программы. Попытайтесь почитать альтернативные источники на тему данного паттерна, так как конкретно этот ролик не раскрыл для вас суть вопроса.
Так или иначе, стратегии где-то и кем-то должны быть созданы. Если говорить очень коротко, то фишка Strategy в том, что мы можем добавлять новые стратегии не меняя код класса Hero.
Автор молодец, что подобынй паттерн озвучивает. Но не сказано о главном смысле подобного паттерна - каждая стратегия это набор уникального поведения. У каждой из стратегий могут быть участки, которые повторяются и в других стратегиях, но все равно уникальная комбинация действий. Именно стратегия позволяет держать код чистым не держа один код с бесконечным количество if else. Пример до конца не раскрывает суть паттерна, а просто выглядит, как абстракция класса Оружие. Вот если бы автор показал, что в зависимости от передаваемого оружия Сквидвара делает разный набор действий - то было бы правильно. А так это просто интерфейс и все.
А кто то пояснит зачем нужно было создавать отдельный класс под разное оружие? Разве это не противоречит принципам solid, в том плане, что можно было унаследовать классы или использовать полиморфизм
Удобная навигация по видео :)
0:00 - Начало
0:39 - Strategy это Behavioral Design Pattern
1:19 - Проблема
4:35 - Концепция Strategy
6:07 - Анатомия Strategy
7:57 - Live example
8:22 - Реализация примера
18:29 - Завершение
Это просто высшее качество реализации обучения. Мои глаза, ушки приятно отдохнули, а мозг все понял. Спасибо.
Очень доступно объясняешь! Супер! Надеюсь, мы будем и дальше изучать шаблоны по твоим урокам!
Просто класс! Огромное спасибо! Мне очень понравился пример со Сквидвардом. Теперь понимаю где допускал ошибки в своих пет проектах.
начал писать консольную игру "саймон говорит" с простыми заданиями чисто для практики, типа верх право прыжок и задумался над расширением команд. нашел ваше видео. это самый быстрый и доходчивый вьезд в паттерн получился. Спасибо!
Классно что сразу же применяете знания на практике 👍 Рад, что видео оказалось полезным!
Теперь все ясно ! Благодарю.
Спасибо! Рассказываешь лучше, чем лицензированный Майкрософт чел из МТС, который половину выдаёт на платных курсах, а бесплатными видео только заманивает.
Объяснения лучшие, пример отличный)
Это лучшее что я когда либо видел. Видео ряд, звуковое сопровождение и конечно подача материала🔥
Очень жду новых видео роликов от Вас... И сдаётся мне такое ощущение, что их уже не будет. Очень печально. =( Вы бы хоть причину назвали, почему решили бросить. У вас видео получается на уровне между "шедевр" и "божественно!"
Он в своём тг ответил, что сейчас работает над большими проектами, поэтому не может делать видео.
@@lkn1ghtl на дату иногда поглядывайте. Для меня это уже не актуально.
@@BrownAleks Ну может кто-то другой бы интересовался, почему бы не ответить?
@@lkn1ghtl для меня актуально, спасибо за ответ)
Каеф, рад что твой канал растёт, очень доходчиво поясняешь :)
Как всегда, очень круто. И понятно.
огромное спасибо! Очень четкое пояснение, удачи с развитием канала)
Топовое качество объяснения. Спасибо!
Как же всё становится просто! Респект!
Спасибо, въехал)))
Кодаза! Давай ещё!
Спасибо! Отличное объяснение. Все понятное сразу стало.
Я просто в шоке, такой контентный контент я только что посмотрел!
Слишком годно, продолжай 😎💥
очень благодарен за ваш труд
Спасибо за урок, очень интересно и понятно 😊
Ну, и чтобы совсем всё было правильно, нужно добавить интерфейс IHero с методом Attack() и реализовать его. Отличный пример, большое спасибо!
Спасибо, очень приятный и полезный ролик.
Один из лучших каналов на которых можно понять базовые вещи по той или иной теме, без ненужной воды и тд, жаль что очень недооценен канал
spasiba drug
Реально стало понятно Спасибо.
Видос топ.
Доступно и понятно. Спасибо =)
круто, спасибо за твой контент, спонсировать не чем пока но рекламы смотрю не пропуская, хоть так какая то копеечка тебе капнет, очень годный контент
Смотрю уроки по Солид но несмотря каждый день возвращаюсь к своему проекту и переписываю код)
Хоть и понимаю этот паттерн, поддержу просмотром!
Отличное объяснение !
Оболденная подача! Впрочем, вы сами это знаете :)
Большое спасибо!)
Спасибо за видео
🔥🔥🔥
Манера изложения автора не оставляет мне шансов быть недоучкой по С# , спасибо автор, снимаю шляпу перед вашим талантом гипнотического воздействия на способность сконцентрировать все ресурсы мозга на впитывание материала
Лучший. Включи воз ожность спон, орства канала, стану донатить пару бак ов в месяц. И ещё запусти мерч с чайкой
Благодарю! По спонсорству, там пока не хватает необходимого количества часов просмотров. Как наберется, можно будет включить. Идея с мерчом интересная, подумаю об этом :)
Очень круто! Спасибо!
На здоровье 💙
Хорошее видео, всё понятно. Но маленький нюанс, можно сделать размер шрифта в IDE в будущих видео чуть больше? На слайдах код прекрасно видно, а вот в IDE я его на слух восстанавливаю. А сидеть сильно близко к телевизору, чтобы всё увидеть, неудобно.
Благодарю за комментарий. Да, в будущих роликах сделаю шрифт крупнее :)
Забавно, что я этим давно пользовался, но не знал что это паттерн стратегия
У Вас было опытно-интуитивное знание, теперь добавилось еще и формальное, что тоже хорошо)
Первое что приходит в голову у новичка - создать класс пухи с различными характеристиками, задавать поведение через конструктор её экземплярам и передавать их уже в целевой класс. Возможно ты пользовался этим подходом? Интерфейсы начинаешь применять когда у объектов совсем уж разная логика, например красная бочка и враг, ну или для всяких кнопок
Мне кажется, что лучше здесь подошёл абстрактный класс, ибо тут строится логика из однотопных объектов - оружий. Интерфейсы больше подходят для тех классов, которые между собой вообще ничем не схожи, то есть выполняют совсем иные действия . Например, интерфейс лучше для такого типа действий: у нас ечть дерево, персонаж и оружие, всё эти объекты совсем разные и мх связать наследованием не получится, тут абстрактный класс не подойдёт, подойдёт интерфейс, например мы зотим, чтобы все эти объекты получали урон, мы просто срздаем интерфейс IDamageble в которм будет метод TakeDamage, и теперь у нас есть уровень абстракции для всех объектов, коиорые могут получать урон, конечно, реализация этих мктово модет быть разной.
Почему такие авторы, как Codaza, Simple Code перестают выпускать видео?! Только появляется надежда, что я пойду все темы в программировании и баац они исчезают из ютуба( Да, понимаю запись новых роликов занимает очень много времени, учитывая ваш щепетильный подход ко всем деталям, но со временем это, наверное, можно было бы как-то масштабировать и выйти на существенный доход...
Возвращайиесь, пожалуйста....
А как в очередной реализации стратегии мы можем обратиться к свойствам контекста-сквидварда. А то тогда не понятно зачем это все. Что если в реализации орудия умерщвления, нам нужно менять состояние контекста, например сквидвард задержал гранату в руке и она взорвалась и теперь он должен получить урон? А то они будто все в воздухе подвешены и ни к чему не привязаны. Это сильно ограничивает возможности реализации.
Все понятно, доступно, круто и т.д., но у меня вопрос.
мы вот это все реализовали, но как это нормально дергать и дать фронтам на растерзание я не понимаю. Ты в Main передаешь конкретные имплементации, но что если мы напишем апи, где параметр будет как раз одно из значений энамки с видео (WaterGun, Plumber, Broom), а мы уже в зависимости от этого параметра должны установить в метод SetWeapon конкретную реализацию интерфейса. У меня в голове все сводится опять же к switch который нарушает вторый принцип SOLID.
Типо:
IWeapon weapon = gunType switch
{
WaterGun => new WaterGun(),
Plumber => new Plumber(),
Broom => new Broom()
};
hero.SetWeapon(weapon);
...
Опять все это придется каждый раз модифицировать при появлении нового значения в энамке. Это можно как то обойти?
Иван, если у Вас есть необходимость избавиться от switch и enum, то можно:
1. Предоставить в API отдельные endpoint-ы под каждый вид оружия.
2. Пробрасывать вызовы, используя паттерн CQRS, на конкретные имплементации обработчиков (handlers). Роутинг можно обеспечить по атрибутам.
Вроде на UML диаграмме неправильно указано включение Стратегии в контекст. Ромбик должен быть с другой стороны, там где контекст.
То есть можно сказать, грубо говоря, что это просто соблюдения 1ого принципа solid с единым интерфейсом для схожих классов?
Доброго времени суток.
А что значит знак вопроса на 12:46 в строчке
private IWeapon? _weapon;
Привет 👋 Это означает, что мы даём явное указание на то, что переменная может принимать значение null.
Если в свойствах проекта Visual Studio 2022, отключить настройку Nullable Context, то, для ссылочных типов, знак вопроса можно не указывать.
@@codaza-channel спасибо!
Подскажи пожалуйста, в чем смысл данного паттерна когда есть внедрение зависимостей?
С таким же успехом паттерн Стратегия можно назвать Тактика.
А если анимация героя зависит от типа оружия. А также, если не все оружия могут быть использованы героем. Как быть?
Действуйте по аналогии с оружием - юзайте паттерн стратегия.
Можно ли сказать, что суть паттерна стратегия - это использовать интерфейсы по назначению?
Нет, это будет слишком общее определение. Интерфейсы используются по назначению в самых разных ситуациях, выходящих далеко за рамки паттерна Strategy.
Если вы хотите услышать суть паттерна одной фразой, то это скорее будет звучать так: выделение схожих алгоритмов с возможностью их использования в объектах, при помощи интерфейсов.
Спасибо за видео, но на 12:12 звук на минуту пропадает.
Благодарю за комментарий. К сожалению, UA-cam вырезал фрагмент из-за фоновой музыки.
А если сделать так что бы просто заменялось название оружия? Разве это не дублирование кода?
Безусловно можно и даже нужно.
Привет! будет паттерн наблюдатель?
Привет! Пока никто не просил. Посмотрим на активность, если будет интересно многим, рассмотрим на канале 🙂
@@codaza-channel тогда я попрошу записать видео об этом паттерне)
Вопрос. А почему в данном случае не использовался абстрактный класс Weapon, и его конкретные реализации? Это же само напрашивается. Или я не прав?
Введение абстрактного класса имеет смысл, когда у нас есть некоторый базовый функционал, который переиспользуется в наследниках. В примере, который мы рассматриваем в видео, производится простой вывод на консоль. На мой взгляд, введение дополнительного слоя абстракции внесло бы избыточную сложность, которая не нужна для понимания механики паттерна Strategy.
В рельных проектах, где Weapon имеет общую логику, абстрактный класс была бы весьма кстати. Так что вы верно уловили суть 🙂
Спасибо! У меня есть вопрос. Изначально было сказано, что метод Attack принимает параметр GunType, почему бы не задать IWeapon в качестве параметра для метода Attack, а создать метод SetWeapon? Это какое-то правило?
Именно это было сделано при реализации живого примера (таймкод: 13:16). Возможно я не понял суть вашего вопроса или Вы не досмотрели видео до конца.
@@codaza-channel Нет, вы не поняли. Почему нужен метод SetWeapon? Почему не сделать метод void Attack(IWeapon weapon) ?
@@dilshodkomilov9121 В ролике я показал классический вариант паттерна Strategy, который предполагает указание стратегии отдельно от выполнения операции. Вариант с указанием стратегии при вызове операции так же является допустимым. Здесь нет строгих рамок.
@@codaza-channel А если IWeapon передать в качестве необязательного параметра конструктора?
@@aaa_aaa6226 Так можно сделать если ваш герой должен быть без оружия или с одним видом оружия на протяжении всей игры. Не думаю что это актуальная логика для игры, но если вам нужно именно такое поведение, то можно так 🙂
А если нужно будет добавить новое оружие, то надо создать новый класс оружия и прописать его как вантус, водный пистолет и т.д.?
просто создаешь этот класс оружия, реализуешь от интерфейса IWeapon и потом у героя сможешь использовать это оружие
Видео как всегда на высоте, но есть и вопросы.
По сути, это же можно реализовать через полиморфизм и тут вопрос, это сам паттерн такой, что позволяет делать выбор в ту или иную сторону или же просто пример так совпал?
Через полиморфизм будет другой паттерн - Visitor (посетитель). Смысл паттерна убрать жесткую зависимость между классом использующим оружие и его поведением. Мы типо написали абстракцию, что хотим, чтобы героя атаковал, а как, чем, это ему не известно
@@dronsan-unity7302 Благодарю, посмотрю ещё про тот паттерн
@@justraccoon3047 да не за что!
Всё понятно, но есть важный вопрос!
Если нам нужно не просто запустить метод Attack(), но и передать в него какие-то параметры при запуске. Для пистолета - 1 параметр, для вантуза - 2 параметра, а для веника - никаких параметров передаваться не нужно. То как реализовать такое?
Ведь это должно указываться непосредственно в классах оружия, а не в самом интерфейсе. Но в таком случае запустить эти методы не получится, т.к. в самом интерфейсе их не будет, к тому же сигнатуры этих методов будут отличаться от сигнатур интерфейса. В общем, это работать не будет. Можно, конечно, указать в интерфейсе все необходимые сигнатуры методов. Но тогда все этих сигнатуры будет нужно реализовать во всех классах оружия. А нам для каждого класса нужен только один метод атаки, но просто принимающий определённые параметры. Надеюсь, мои рассуждения не слишком запутаны.
Т.е. вопрос по сути такой: что делать, если нам нужно, чтобы для метода Attack() у каждого оружия была разная сигнатура (принимаемые аргументы)?
Заранее благодарю за ответ!
Ты можешь добавить эти параметры в класс конкретного оружия и уже в методе атака делать то, что тебе нужно.
@@bamblebi1773 А как мне ПЕРЕДАТЬ в этот класс параметры? Если у разных классов - разные параметры. Перечитайте ещё раз то, о чём я спросил в комментарии, на который вы ответили. Суть именно в передаче аргументов. Если у вас есть ответ на этот вопрос - буду признателен.
@@aleksey8405 У разного оружия могут быть разные параметры/настройки, поэтому при описании класса с конкретным оружием необходимо добавить поля для этих параметров.
Дальше в конструкторе передавать эти параметры при создании экземпляра конкретного оружия, либо через свойства.
Далее, в методе Attack конкретного оружия, вы можете использовать эти параметры.
@@bamblebi1773 Использовать свойства? Нельзя обратиться через тип данных интерфейса к свойствам, которые не указаны в самом интерфейсе.
Метод Attack может быть разным для каждого класса, но его сигнатура - должна быть одинаковой для всех. Вы не можете для одного из классов сделать сигнатуру, принимающую, например int и string. А для другого - только int. А для третьего - вообще ничего не принимающую. Этот метод должен быть одинаковым для всех, иначе код не скомпилируется. Это принцип работы интерфейсов.
И программа ничего не знает о тех параметрах, которые вы добавили дополнительно в какой-то из классов. Потому что они не указаны в интерфейсе. Вы не сможете обратиться к ним через тип данных интерфейса. Вы не можете передать никаких аргументов, уникальных для каждого класса. Только общие, заданные в интерфейсе. И здесь нужно либо использовать привидение типов, например. Но это плохая практика.
Понимаете, о чём я?
@@aleksey8405 Извините, я неправильно написал где использовать эти параметры. Не в методе Attack, а в методе Shoot конкретного оружия. А при создании оружия, создавать его с необходимыми параметрами.
Таким образом, каждое оружие будет обладать своими параметрами, и исходя из этих параметров будет реализован метод Shoot.
мало, очень мало лайков!
Поднажмём 😬
А в чем различие между Strategy и Dependency Injection?
DI - это не паттерн, а определенный прием ООП. И как раз этот прием может применяться уже в паттернах и не в одном.
@@phat80 а разве паттерн - это не есть определенный прием программирования?
@@xinitru в моем понимании, паттерн - это комбинация из нескольких приемов. Может я не прав, не претендую на истину в последней инстанции. Ну по сути любой паттерн - это набор простейших понятий и приемов. Такие легкие понятия, как наследование, агрегирование, композиция и т.д., объединяются в какую-то более сложную схему, которая и называется паттерном.
@@phat80 Ну Интернет с Вами не согласен: Design patterns are typical solutions to commonly occurring problems in software design. И Dependency Injection практически везде называют паттерном.
На самом деле, я нашел ответ о различиях. Стратегия применяется для случаев, когда классу необходимо определить разнообразные меняющиеся на протяжении его жизненного цикла действия. А Внедрение Зависимостей обычно применяется для однократного определения реализации поведения в начале жизненного цикла объекта, не меняющегося до его уничтожения.
Например, в видео, Сквидвард то вантузом атакует, то бумерангом, то еще чем-то. При использовании Внедрения Зависимостей, мы бы еще в начале жизни задали ему конкретный способ атаки, и дальше он бы атаковал только так.
@@xinitru ну не согласен, так не согласен. Такое впечатление, что вы задали кому-то вопрос именно с целью написать, что интернет с этим кем-то не согласен 😂 Доказывать свою правоту не буду, так как не имею на это право, ибо сам в ООП имею только какие-то базовые знания и вероятно неправильные, как выясняется.
Какой же хороший звук, аж приятно слушать.
Очень похож на патерн состояние.
Обязательно ли использовать интерфейс? Можно ведь использовать абстрактный класс вместо интерфейса в котором будет своя какая-то реализация:
abstract class Weapon
{
public abstract string WeaponName { get; }
public abstract int Damage { get; }
public void Shoot(string nickname)
{
Console.WriteLine($"{nickname} атаковал используя {WeaponName} и нанёс {Damage} DMG!");
}
}
class Bow : Weapon
{
public override string WeaponName => "Лук";
public override int Damage => 12;
}
// Действия в классе Hero точно такие же как в видео, просто меняем IWeapon на мой класс Weapon
Будет ли это реализацией стратегии?
Если честно мне кажется, что я не до конца понимаю когда надо использовать интерфейс, а когда абстр. класс. Заранее спасибо большое за ответ! Надеюсь понятно объяснил свой вопрос
Как то принято через интерфейсы все паттерны делать, но абстрактный класс так же можно использовать - что абстрактный класс, что интерфейс являются абстракцией, на базе чего и строится смысл паттерна
@@dronsan-unity7302 я уже разобрался, но спасибо за ответ)
@@vladrz2525 да не за что)
В теории все понятно. Но на практике - полнейший туман. Раз уж упоминаются игры, то вспоминается Unity. Но какие там могут быть new при объединении интерфейсов вместе с MonoBehavior?.. Да никаких. Получается, что все эти дополнительные сущности - обычные костыли к MonoBehavior и префабам. Ничего они не упрощают по большому счету. Но в консоли красиво смотрится )
К сожалению, я не работаю с Unity, поэтому не смогу прокомментировать этот момент. Однако не списывайте паттерн Strategy со счетов, так как это не паттерн плохой, а скорее мне не удалось донести до вас его суть в понятном для вас ключе.
Могу лишь добавить, что с точки зрения backend разработки, этот паттерн является одним из часто используемых, так как позволяет расширять логику классов без их модификации. Даже, с точки зрения десктопных приложений (например, Photoshop), как добавить какой-нибудь плагин? Плагину нужно реализовать интерфейс и далее его можно добавить в основную логику программы. Попытайтесь почитать альтернативные источники на тему данного паттерна, так как конкретно этот ролик не раскрыл для вас суть вопроса.
Не совсем понятно в чем заключается инкапсуляция алгоритмов если вы создаете их в Main
Так или иначе, стратегии где-то и кем-то должны быть созданы. Если говорить очень коротко, то фишка Strategy в том, что мы можем добавлять новые стратегии не меняя код класса Hero.
спасибо, нифига не понял хД
+
Автор молодец, что подобынй паттерн озвучивает. Но не сказано о главном смысле подобного паттерна - каждая стратегия это набор уникального поведения. У каждой из стратегий могут быть участки, которые повторяются и в других стратегиях, но все равно уникальная комбинация действий. Именно стратегия позволяет держать код чистым не держа один код с бесконечным количество if else. Пример до конца не раскрывает суть паттерна, а просто выглядит, как абстракция класса Оружие. Вот если бы автор показал, что в зависимости от передаваемого оружия Сквидвара делает разный набор действий - то было бы правильно. А так это просто интерфейс и все.
а не лучше было бы реализовать абстрактный класс оружия?
Можно. Но логически и эстетически, в примере, правильнее будет интерфейс.
объяснение хорошее, но звук маркера ппц как раздражает.
звук 12 40 пропал.... ну как так то?
А кто то пояснит зачем нужно было создавать отдельный класс под разное оружие? Разве это не противоречит принципам solid, в том плане, что можно было унаследовать классы или использовать полиморфизм