События
Автор: Дмитрий Прокопьев
У вас когда-нибудь случалось такое, что один компонент влез в зону ответственности другого? Ситуация, когда на такой компонент сваливалась вся работа и из за этого он становился перегруженным? С этим рано или поздно сталкиваются все, но не все знают, как решить эту проблему.
Пример проблемы
Представим, что мы работаем над игрой, в которой персонаж может зарабатывать игровую валюту и тратить ее в магазине. Для этого мы сделали ему простой кошелек:
У этого кошелька одна простая ответственность: проводить транзакции и обеспечивать их корректность. Но теперь нам прислали новую задачу: отображать количество средств на экране. Не проблема, мы уже реализовали класс WalletView
, который умеет отображать количество средств. Осталось лишь вызвать у него метод:
Нам опять пришла новая задача! Теперь каждый раз, когда происходит транзакция, нужно сделать сохранение в файл, чтобы запомнить сколько денег теперь есть у игрока. Не проблема, мы уже реализовали класс FileSaver
, который умеет сохранять количество денег. Нужно лишь вызвать у него метод:
Удивительно, опять новая задача! Теперь магазин должен предлагать игроку новые товары, когда тот произвел транзакцию. Не проблема, обратимся к классу Shop
:
Видите, куда это идет? Вот так теперь выглядит метод AddMoney
у кошелька:
Бред, так ведь? Теперь кошелек делает совершенно не свою работу. Как нам в будущем догадаться, что именно кошелек делает все это? Как понять, почему магазин внезапно перестал работать, когда мы всего лишь убрали кошелек у игрока? Как понять, почему кошелек отказывается работать, когда мы всего лишь выключили интерфейс? Много вопросов - мало ответов.
Суть проблемы
Где в этой ситуации корень зла? Когда мы допустили роковую ошибку? Мы сделали это тогда, когда повесили на кошелек задачи других компонентов. Но как этого избежать, если только кошелек знает, что происходит с деньгами?
Например, кошелек может уведомить всех, что происходит, но не указывать компонентам, что именно делать. Тогда ответственность за реакцию компонентов переляжет с кошелька на них самих. Мысленно представим такой диалог:
Заметьте, как кошелек больше не отвечает за остальных! Он сообщил информацию и на этом успокоился. Так мы и можем решить эту проблему.
И какое отношение к этому имеют события?
Событие (англ. Event) - это механизм, позволяющий организовать общение между компонентами описанным выше образом. Название "Событие" появилось, потому что сообщение, которое передает компонент, говорит, что "что-то случилось" или "произошло какое-то событие". То есть событием называется само "сообщение".
Тот компонент, который сообщает информацию через событие, называется владельцем события. Помните, как некоторые компоненты услышали сообщение, а некоторые нет? Одни называются "слушателями" (англ. Listeners) или "подписчиками" события, потому что они получают из него информацию. А другие никак не называются, не хотят - не слушают.
Чтобы стать слушателем события, нужно на него подписаться (англ. Subscribe), а чтобы перестать быть слушателем нужно отписаться (англ. Unsubscribe).
Что с этим делать дальше?
Last updated
Was this helpful?