| title | Занятие 25 |
|---|---|
| description | Связь модулей - от интерфейсов до EventBus |
Для начала два термина - связность(cohesion) и связанность(coupling).
Связность - на сколько составные части направлены на решение одной задачи.
Связанность - на сколько одни модули зависят от других (и как много они знают друг о друге)
Это значит, что программный компонент имеет небольшое число внешних связей и отвечает за решение близких по смыслу задач.
Слабое зацепление (Low Coupling) и Высокая связность (High Cohesion) это 2 из 9 шаблонов GRASP
Высокая связность говорит об эффективности программы (или ее отдельных модулей).
Низкая связанность означает легкость рефакторинга и переиспользуемость кода.
Наблюдатель - подход (паттерн), позволяющий одним объектам следить и реагировать на события, происходящие в других объектах.
На самом деле вы с ним уже работали - это EventTarget
Данный шаблон часто применяют в ситуациях, в которых отправителя сообщений не интересует, что делают получатели с предоставленной им информацией.
Может быть представлен как
IObservable {
addObserver(event, handler)
removeObserver(event, handler)
notifyObserver(event, data)
}или
EventTarget {
addEventListener(event, handler)
removeEventListener(event, handler)
dispatchEvent(event)
}или
Backbone.Events {
on(event, handler)
off(event, handler)
trigger(event)
}Иногда могут добавлять вспомогательные методы, например
Backbone.Events {
// ...
once(event, handler)
}document.querySelector(element).addEventListener("click", (ev) => {
alert("Boom!");
});Оговорка: чаще всего обработчиком события является функция. Но это также может быть и объект (EventListener) - в зависимости от реализации.
Посредник - это поведенческий паттерн проектирования, который позволяет уменьшить связанность множества классов между собой, благодаря перемещению этих связей в один класс-посредник.
Задача: Обеспечить взаимодействие множества объектов, сформировав при этом слабую связанность и избавив объекты от необходимости явно ссылаться друг на друга.
Решение: Создать объект, инкапсулирующий способ взаимодействия множества объектов.
Преимущества: Устраняется связанность между "Коллегами", централизуется управление.
Самый распространенный (и простой) вариант реализации паттерна - с использованием EventEmitter интерфейса (Event Bus - Шина событий).
Разница, по сравнению с обычным использованием EventTarget:
- события в EventTarget генерирует сам объект, при работе с EventBus это делают сторонние объекты
- список событий при работе с EventTarget ограничен устройством объекта, при работе с EventBus он определяется участниками
При этом, чтобы избежать коллизии имен событий, зачастую вводят namespaces, в формате {NAMESPACE}:{EVENT NAME}. Например user:add, searchHistory:add.
Нужно отметить, что по-хорошему, префиксы делаются на основе сущностей, а не на основе модулей (иначе происходит раскрытие структуры системы).
const eventBus = new EventBus();
// module 1
eventBus.on("city:changed", (cityName) => console.log(`New city: ${cityName}`));
// module 2
eventBus.trigger("city:changed", "Minsk");Как мы могли бы применить это к уже сделанным домашним заданиям?
Реализовать поверх существующего функционала метод once (для одноразового вызова обработчика).
Дополнительные материалы:

