Паттерн Observer, С#, unity, gamedev,

Поділитися
Вставка
  • Опубліковано 29 вер 2024

КОМЕНТАРІ • 37

  • @PaulZabelin
    @PaulZabelin Рік тому +11

    Братан, хорош, давай, давай вперед! Контент в кайф, можно ещё? Вообще красавчик!

    • @sergeykazantsev1655
      @sergeykazantsev1655  Рік тому

      О, ребятушки с ExtremeCode пожаловали) Спасибо за комменты)

  • @shelikhann
    @shelikhann 5 місяців тому

    Классно, понятно, интересно, виртуозно

  • @g4sasha
    @g4sasha 7 днів тому

    8:45 То есть мне каждому классу, который имплементирует интерфейс ISubject нужно каждый раз прописывать 3 метода, 2 из которых всегда повторяют проверку if и добавление в лист? И ещё сам лист? Я с ума не сойду, если у меня таких классов много? Можно конечно копировать, но это звучит не правильно

    • @sergeykazantsev1655
      @sergeykazantsev1655  7 днів тому +1

      Далее по видео я показал, куда Observer эволюционировал - на 12:20 можете посмотреть :)
      Там компактнее получилось

    • @g4sasha
      @g4sasha 7 днів тому

      Спасибо) ​@@sergeykazantsev1655

    • @ПётрЖуков-ж6т
      @ПётрЖуков-ж6т 5 днів тому

      Если нужен "голый" наблюдатель (не через events), то с С#8 мы можем дать в интерфейс типовую реализацию методов. Вещь сомнительная, но если следить за тем, чтобы не просачивалась конкретика в интерфейс, то это можно сделать так. Методы здесь работают только с тем, что есть внутри интерфейса, инкапсуляция не нарушается, но с явной реализацией в интерфейсах нужно быть крайне осторожным.
      public interface ISubject
      {
      ICollection Observers { get; init; }
      void Attach(IObserver observer)
      {
      if(!Observers.Contains(observer)) Observers.Add(observer);
      }
      void Detach(IObserver observer)
      {
      if (Observers.Contains(observer)) Observers.Remove(observer);
      }
      void Notify();
      }
      UPD: Notify все таки лучше оставить нереализованным.

  • @shlembert
    @shlembert Рік тому +7

    Сергей, спасибо! Материал востребованный, подача безупречная!
    Скинул линк на ваш видос сокурсникам. Поржали с Лунтика.
    Хотел бы увидеть столь же усвояемый материал по DIP в реализации Zenject
    Ну и по остальным принципам SOLID в таком же стиле!
    Спасибо от сообщества!

    • @sergeykazantsev1655
      @sergeykazantsev1655  Рік тому +2

      Спасибо, OCP уже выложил, DI тоже в планах)

    • @VyacheslavTamplier
      @VyacheslavTamplier Рік тому

      По Zenject было бы интересно послушать. Но там отдельный плейлист нужен будет :)

  • @COOKIEMONSTER90
    @COOKIEMONSTER90 Рік тому +2

    12:06 Нынче вроде можно ивенты проверять на нуль одной строкой, вот так: Event?.Invoke()

  • @VyacheslavTamplier
    @VyacheslavTamplier Рік тому +1

    Очень хорошо объясняете! Спасибо!

  • @vockinmine3921
    @vockinmine3921 4 місяці тому

    Спасибо чел, я прям прозрел когда посмотрел твоё видео. У меня будето пазл в голове сложился. Спасибо!

  • @mikhail6384
    @mikhail6384 7 місяців тому

    Очень круто объясняете. Приятно слушать и смотреть, спасибо!

  • @p.polunin
    @p.polunin 7 місяців тому

    Повторение, мать учения!

  • @МиксОрешный
    @МиксОрешный 6 місяців тому

    Тут единственный вопрос в конце к методу UpdateUI у HealthBar. А не лучше его сделать приватным, чтобы только сам класс решал, когда и как он будет обновлять полоску здоровья? А то вдруг злой геймменеджер снаружи его ради прикола будет вызывать? Или есть какой-то смысл его оставить публичным?

    • @sergeykazantsev1655
      @sergeykazantsev1655  6 місяців тому

      на 9:07 я как раз сделал UpdateUI приватным, насколько я помню, разве нет?) Или вопрос про HealthChanged?

  • @MrG12g
    @MrG12g Рік тому

    тупа лайк под каждым видео, по твоим видосам можно и мидлом стать

  • @mar_vi_a
    @mar_vi_a Рік тому

    Ничего не понятно, но подписалась))

  • @COOKIEMONSTER90
    @COOKIEMONSTER90 Рік тому

    Кстати, очень бы не помешали примеры по разным паттернам, но не в ООП, а в Дата-ориентированном программировании в Юнити. Не планируется ли случайно такого в ближайшее время?

    • @sergeykazantsev1655
      @sergeykazantsev1655  Рік тому +1

      Планируется, но не в ближайшее время)

  • @COOKIEMONSTER90
    @COOKIEMONSTER90 Рік тому +2

    Сегодня бежал с работы домой, не успел добежать и на пол пути реализовал интерфейс АйОбсёрвер. Inventory.attire.pants.SetDirty()
    Шютка))

    • @sergeykazantsev1655
      @sergeykazantsev1655  Рік тому +1

      Да, главное аккуратнее работать с классом VokzalnayaShaurma, он прям мотивирует подобный интерфейс реализовать)

    • @COOKIEMONSTER90
      @COOKIEMONSTER90 Рік тому

      @@sergeykazantsev1655 =)

  • @ichbinschlange
    @ichbinschlange 8 місяців тому

    8:54 Интерфейс, как и абстрактный класс, позволяет использовать protected.

    • @sergeykazantsev1655
      @sergeykazantsev1655  7 місяців тому

      Это очень здорово, но здесь то это к чему?

    • @ichbinschlange
      @ichbinschlange 7 місяців тому

      @@sergeykazantsev1655, к "в интерфейсе приватные поля не создашь". private не создашь, protected создашь, что в сущности тоже самое.

  • @PinkPanteRus
    @PinkPanteRus Рік тому

    Спасибо!

  • @vlpalamar8639
    @vlpalamar8639 Рік тому

    получается современная версия паттерна это просто action в классе object и подписка/отписка нужного метода от него в классе observer? никих интерфейсов, ничего. правильно?

    • @sergeykazantsev1655
      @sergeykazantsev1655  Рік тому

      если я Вас правильно понимаю, то скорее всего да. В подписке и отписке на экшны интерфейс не нужен. Но тут очень важно понимать, что если Вы на собесе скажете, что паттерн Observer это просто action в классе Object, и там подписка и отписка нужного метода без интерфейсов - я думаю, собеседующий этот ответ не одобрит. Тут в Observer важен сам принцип - взаимодействия между классами через события. Реализуете ли вы его классически или через action-ы - это уже вторично)

    • @vlpalamar8639
      @vlpalamar8639 Рік тому

      ​@@sergeykazantsev1655 благодарю за ответ)

  • @Guy-qv8bq
    @Guy-qv8bq Рік тому

    Здравствуйте. Хотел задать вопрос. Насколько я понимаю функционал паттерна Observer как и использование событий в данном случае, можно заменить на реактивные свойства, которые реализованы в том же UniRx. Хотел спросить все ли правильно я понимаю.

    • @sergeykazantsev1655
      @sergeykazantsev1655  Рік тому

      Да, всё верно. UniRx это продолжение развития паттерна Observer. Там так же есть подписки, отписки, уведомления и реакции на уведомления, только они имеют более удобный вид. UniRx как я понимаю вообще на этом выстроил свою философию кода, со своим IObservable и подписками на потоки данных

    • @Guy-qv8bq
      @Guy-qv8bq Рік тому

      @@sergeykazantsev1655 Спасибо за ответ. Вы делаете очень крутой обучающий контент. Буду с нетерпением ждать от вас новых видео)

  • @dmitryzolkin7904
    @dmitryzolkin7904 Рік тому

    Есть более удобный способ использования Наблюдателя без интерфейсов.
    - Создаём класс события, являющимся ScriptableObject.
    - Примерная реализация:
    [CreateAssetMenu]
    public class GameEvent : ScriptableObject
    {
    private List _listeners = new List();
    public void Subscribe(Action newListener)
    {
    if (_listeners.Contains(newListener))
    {
    Debug.LogError($"Попытка повторного добавления {newListener} в список подписчиков события {name}.");
    return;
    }
    _listeners.Add(newListener);
    }
    public void Unsubscribe(Action listener)
    {
    if (!_listeners.Contains(listener))
    {
    Debug.LogError($"Попытка удалить несуществующего подписчика {listener} из списка подписчиков события {name}.");
    return;
    }
    _listeners.Remove(listener);
    }
    public void Publish()
    {
    if (_listeners.Count == 0)
    {
    Debug.LogError($"Попытка инициировать событие {name}, у которого нет подписчиков");
    return;
    }
    for (int i = 0; i < _listeners.Count; i++)
    _listeners[i].Invoke();
    }
    }
    - Для каждого события создаём отдельный экземпляр с уникальным именем в ассетах.
    - Ссылки на конкретный экземпляр должны быть у издателя и подписчика(ов).
    - Издатель просто вызывает Publish() когда нужно. Подписчик просто передаёт метод в Subscribe([имя метода]), который должен обрабатывать событие.
    - Для событий с аргументами можно расширить класс GameEvent.
    Это позволяет подписчикам знать только о событиях, игнорируя подробности о субъектах. Самому событию без разницы кто его публикует и обрабатывает.

    • @sergeykazantsev1655
      @sergeykazantsev1655  Рік тому

      Ну это сигнальная шина некая получается, у меня по EventBus даже видео на канале есть)

  • @ИванДовлатов-х3ж
    @ИванДовлатов-х3ж 6 місяців тому

    Мощно💪