Борислав@handeh0ch
Frontend-разработчик
Информация
- В рейтинге
- Не участвует
- Откуда
- Свердловская обл., Россия
- Зарегистрирован
- Активность
Специализация
Фронтенд разработчик, Веб-разработчик
Средний
Git
JavaScript
TypeScript
Node.js
Angular
SCSS
Веб-разработка
HTML
CSS
Спасибо большое за комментарий! Вы не первый, кто написал о том, что не хватает реальных практических примеров для демонстрации подхода. Я учту это в своих будущих работах.
Согласен. Стоило упомянуть привычные кейсы использования
multi, такие как интерсепторы илиVALUE_ACCESSOR, для более подробного описания темы. Однако в данной статье речь больше про кейсы, когда требуется регистрировать список различных реализаций и уметь получать необходимую реализацию, в зависимости от внешних факторов.Речь идёт о регистрации реализаций в один скоуп в иерархии для дальнейшего взаимодействия с ними, как вы написали чуть ниже. Давайте приведу несколько примеров, где это может оказаться удобным.
Пример 1
Представим, что мы разрабатываем конструктор форм (для примера взят скриншот с яндекс форм). В данном случае мы создам некоторый контракт
IWidgetConfigurator, который будет иметь полеkeyи прочие общие методы для работы с виджетом. Для каждого виджета будет создана своя реализация данного интерфейса, которая будет предоставлять специфические данные, настройки, модели для конкретного виджета (можно придумать разные отвественности для этого сервиса). Во время драг-н-дропа виджета из сайдбара на форму у нас будет появляться компонента данного виджета (в примере "Один вариант"). Все эти виджеты будут унаследованы от базовой компоненты виджета и иметь некоторое абстрактное полеtype, которое будет реализовано в наследниках. По этому полюtypeмы сможем получать из сервиса-менеджера необходимую реализацию для настройки активного виджета.Пример 2
За вторым примером далеко ходить не пришлось — конструтор параграфа на хабре тоже мог бы быть реализован с помощью данного подхода.
В данном случае у нас есть компонента конструктора параграфа, в которую мы можем зарегистрировать список виджетов. Каждый виджет будет реализовывать некоторый интерфейс.
Также есть селект-контрол, который содержит список опций в форматe
{ имя_виджета, ключ_виджета }. Когда мы кликаем на опцию селекта происхдитvalueChangesс новым ключом и мы можем добавить виджет на параграф, выбрав реализацию из менеджера по ключу виджета.В данных случаях использоавние описанного подхода считаю достаточно уместным, оправданным и удобным.
Под один токен регистрируются разные реализации одного контракта, которые могут подменяться в зависимости от состояния приложения. Если бы у вас было три реализации и каждая была бы зарегистрированна отдельно, вто в коде вам бы приходилось получать все три релизации, а затем определять которую из них использовать.
Спасибо за отзыв! Постараюсь добавлять больше конкретных примеров в будущем.
В ангуляре реализуется паттерн Injection Key, который позволяет регистрировать зависимости в DI-контейнер по уникальному ключу, а затем получать их с помощью этого ключа. Однако, возникают ситуации, что по одному ключу регистрируется список зависимостей с помощью опции провайдера
multi: true. Такой подход подразумевает, что мне нужно как-то получать конкретную реализацию из списка. То есть связь между ключём и значением становится не one to one, а one to many.Представим, что у меня есть 10 сервисов, которые я регистрирую, через multi.
Если я попытаюсь сделать
inject(EXAMPLE_SERVICE_TOKEN), то вместо одного инстанса получу список инстансов. Но как мне выбрать нужный инстанс из списка? Допустим у меня есть некоторый select-control, и я хочу, чтобы из DI бралась новая реализация, каждый раз, когда отрабатываетvalueChanges, в зависимости от значения селекта.Как раз для этого мне будет удобно использовать сервис-менеджер, чтобы по ключу получать конкретный сервис из списка.
Например можно создать в сервисе-менеджере метод
has(key: TKey): boolean, который будет говорить зарегистрирован ли сервис по такому ключу или нет. Для этой задачи можно придумать множество решений и расширить базовый функционал.