В качестве продолжения к предыдущей статье об общем состоянии для компонентов, дальше развиваю тему и хочу реализовать фичу, которая позволит отлавливать и обрабатывать в каждом компоненте событие по изменению состояния (когда данные в общем состоянии изменяются в каком-то компоненте).

Ссылка на проект

Обычно для того, чтобы отследить изменение данных, в каком то компоненте, создается прямая связь, то есть мы, либо в методе Update проверяем, не изменились ли там данные


Пофреймовая проверка данных через метод Update

либо подписываемся на вполне конкретное событие, которое вызывается самостоятельно в «отслеживаемом» компоненте, и в конечном потом обрабатывается.


Подписка на событие в компоненте и обработка его

Есть множество недостатков в таком подходе, которые по большей части описаны в прошлой статье. Главная общая причина этих недостатков это сильная связанность и сложная maintenance (способность поддерживать, развивать проект, рефакторить).

Создание решения «Уведомления об изменении состояния»


Теперь когда имеется система, позволяющая ослабить связь между компонентами и средства для создания рассылок между компонентами, можно избавиться от ручной проверки значений в общем состоянии, следующим образом:


Схема уведомления об изменении общего состояния

В реализации, описанной в предыдущей статье, данные изменяются в одном месте, в индексаторе компонента SharedState и поэтому контролировать их изменение очень просто


Индексатор в общем состоянии

В сеттере индексатора мы присваиваем значения состояния.

Теперь для SharedState компонента нужно добавить зависимость от SharedEvents, так как именно его и буду использовать для отправки уведомлений. Добавим атрибут для SharedState


Добавление зависимости в SharedState от SharedEvents

И создам класс, наследуемый от EventData, для отправки данных в уведомлении об изменении состояния. Он будет содержать название параметра, в состоянии и его новое значение


Добавление класса, который содержит информацию об изменении в общем состоянии

Теперь нужно добавить ссылку на SharedEvents, получив ее из игрового объекта в компоненте SharedState


Получение SharedEvents в компоненте SharedState

Теперь изменим сеттер индексатора таким образом, чтобы при каждом изменении состояния создавалось уведомление с именем «sharedstatechanged» и передадим объект, содержащий все данные об изменении


Изменение сеттера индексатора

Теперь осталось подписаться на изменения в каком либо компоненте, изменить данные в другом и проверить как это работает.

Допустим SecondComponent меняет состояние, например параметр «somedata», а компонент FirstComponent отслеживает изменение состояния, подписавшись на уведомления

В SecondComponent вызовем изменение параметра


Вызов изменения данных

И теперь в методе FirstComponent добавляем обработчик и выводим в консоль информацию об изменении общего состояния


Обработка события об изменении общего состояния

Теперь если запустить игру, после того как общее состояние будет изменено в SecondComponent, в компоненте FirstComponent мы получим уведомление и выведем данные в консоль



Теперь, когда это работает, можно немного отрефакторить и сделать код еще более удобным. Для этого нужно перенести подписку на уведомления об изменении общего состояния в базовый класс SharedStateComponent и создать абстрактный метод, реализовав который каждый компонент будет обрабатывать в нем изменения состояния, или нет, на усмотрение компонента.

Переносим подписку в SharedStateComponent


Подписка на уведомления об изменении общего состояния в базовом классе

Добавляем абстрактный метод и вызываем его в обработчике события


Добавление абстрактного метода, для обработки события в дочерних классах

И теперь в каждом дочернем компоненте FirstComponent и SecondComponent нужно реализовать этот метод и обработать в нем изменение общего состояния. Но мы как и прежде просто выведем это в консоль


Имплементация абстрактного метода в компонентах FirstComponent и SecondComponent

И теперь когда мы запустим игру мы увидим 2 записи в консоли, из обоих компонентов.



Важно!


В предыдущей реализации был баг в классе SharedEvents и чтобы его пофиксить нужно изменить метод Subscribe на:

Комментарии (2)


  1. BertoldHolz
    03.02.2019 19:10

    Не верьте в демократию;) Пишите дальше.
    Если можно названия проектов или хотя бы описание проектов, в которых вы применяли данную архитектуру.


    1. deniskozlov Автор
      03.02.2019 19:12

      www.youtube.com/channel/UCHoPgKnYAwkQ9u4wtDZdeBQ/videos?sort=dd&view_as=subscriber&view=0&shelf_id=0
      Тут лог разработки прототипа, где это применяется