js-service
Языки
- JavaScript100%
@e22m4u/js-service
Модуль реализует принцип инверсии управления (Inversion of Control), через паттерн Service Locator в связке с DI-контейнером. Встроенные классы данного модуля берут на себя ответственность за создание, хранение и жизненный цикл объектов, освобождая зависимости приложения от жестких связей и ручного вызова конструкторов.
Содержание
- Установка
- Описание
- Базовые примеры
- ServiceContainer
- Иерархия контейнеров
- Service
- DebuggableService
- Тесты
- Лицензия
Установка
Модуль поддерживает ESM и CommonJS стандарты.
ESM
CommonJS
Описание
Модуль экспортирует два основных класса и ,
которые можно использовать как по отдельности, так и вместе для построения
слабосвязанной архитектуры.
-
(IoC-контейнер)ServiceContainer
Реализация сервис-контейнера для хранения и разрешения зависимостей. -
(базовый класс для наследования сервисами)Service
Инкапсулирует работу с сервис-контейнером, предоставляя наследуемым от него сервисам простой интерфейс для доступа к зависимостям.
Дополнительно:
(базовый Service + инструменты логирования)DebuggableService
Расширенная версия классас дополнительным функционалом для логирования.Service
Базовые примеры
Создание контейнера и экземпляра сервиса по принципу «одиночки».
Использование сервиса внутри другого как зависимость.
Сервис как точка входа приложения.
Подмена сервиса в контейнере.
ServiceContainer
В роли IoC-контейнера выступает класс . Он отвечает
за регистрацию, создание и предоставление экземпляров сервисов (зависимостей).
Методы:
получить существующий или новый экземпляр;get(ctor, ...args)получить существующий или новый экземпляр, только если указанный конструктор зарегистрирован в контейнере, в противном случае выбрасывается ошибка;getRegistered(ctor, ...args)проверить существование конструктора в контейнере;has(ctor)добавить конструктор в контейнер (ленивая инициализация);add(ctor, ...args)добавить конструктор и сразу создать экземпляр;use(ctor, ...args)добавить конструктор и связанный с ним готовый экземпляр;set(ctor, service)получить родительский сервис-контейнер;getParent()проверить наличие родительского сервис-контейнера;hasParent()
В сигнатурах методов используется вспомогательный тип конструктора:
serviceContainer.get
Метод класса создает экземпляр
полученного конструктора и сохраняет его для последующих
обращений по принципу "одиночки" (Singleton).
Сигнатура:
Пример:
Метод может принимать аргументы конструктора. При этом, если контейнер
уже имеет экземпляр данного конструктора, то он будет пересоздан с новыми
аргументами.
Пример:
serviceContainer.getRegistered
Работает аналогично , но выбрасывает ошибку, если конструктор
сервиса не был предварительно зарегистрирован через , или .
Это обеспечивает более строгий контроль над зависимостями.
Сигнатура:
Пример:
serviceContainer.has
Проверяет, зарегистрирован ли конструктор в контейнере (или в одном
из его родительских контейнеров). Возвращает или .
Сигнатура:
Пример:
serviceContainer.add
Регистрирует конструктор в контейнере, но не создает экземпляр в момент вызова. Экземпляр будет создан только при первом доступе к сервису. Метод позволяет указать аргументы, которые будут использованы для создания экземпляра.
Сигнатура:
Пример:
Аргументы, переданные в , будут использованы при создании
экземпляра, если будет вызван без аргументов.
serviceContainer.use
Немедленно создает и кэширует экземпляр сервиса. Может использоваться, когда сервис должен быть проинициализирован сразу при настройке другого компонента.
Сигнатура:
Пример:
serviceContainer.set
Метод позволяет связать конструктор с уже существующим экземпляром. Может быть использован для подмены зависимостей в тестах или для внедрения экземпляров, созданных вне контейнера.
Сигнатура:
Пример:
serviceContainer.getParent
Метод возвращает родительский контейнер. Если у текущего контейнера нет родителя, то метод выбрасывает ошибку.
Сигнатура:
Пример:
serviceContainer.hasParent
Метод проверяет наличие родительского контейнера и возвращает логическое
значение. Данный метод полезен перед вызовом метода , который
выбрасывает ошибку при отсутствии родителя.
Сигнатура:
Пример:
Иерархия контейнеров
Конструктор первым параметром принимает родительский
контейнер, который используется как альтернативный, если конструктор
запрашиваемого сервиса не зарегистрирован в текущем.
Service
Методы:
получить существующий или новый экземпляр;getService(ctor, ...args)получить существующий или новый экземпляр, только если указанный конструктор зарегистрирован в контейнере, в противном случае выбрасывается ошибка;getRegisteredService(ctor, ...args)проверить существование конструктора в контейнере;hasService(ctor)добавить конструктор в контейнер;addService(ctor, ...args)добавить конструктор и создать экземпляр;useService(ctor, ...args)добавить конструктор и его экземпляр;setService(ctor, service)
Сервисом может являться совершенно любой класс. Однако, если это
наследник класса , то такой сервис позволяет инкапсулировать
создание сервис-контейнера, его хранение и передачу другим сервисам.
Пример:
В примере выше мы не заботились о создании контейнера и его передачу
между сервисами, так как эта логика инкапсулирована в базовом
классе .
service.getService
Метод обеспечивает существование единственного экземпляра
запрашиваемого сервиса, и не создает новый экземпляр при повторных
обращениях. Однако, при передаче дополнительных аргументов, сервис
будет переопределен с новыми аргументами конструктора.
Сигнатура:
Пример:
service.getRegisteredService
Работает аналогично , но выбрасывает ошибку, если конструктор
сервиса не был предварительно зарегистрирован, что обеспечивает более
строгий контроль над зависимостями.
Сигнатура:
Пример:
service.hasService
Проверяет, зарегистрирован ли конструктор в контейнере. Возвращает
или . Полезно для условного запроса зависимостей.
Сигнатура:
Пример:
service.addService
Регистрирует конструктор в контейнере, но не создает экземпляр в момент вызова. Экземпляр будет создан только при первом доступе к сервису. Метод позволяет указать аргументы, которые будут использованы для создания экземпляра.
Сигнатура:
Пример:
service.useService
Немедленно создает и кэширует экземпляр сервиса. Может использоваться, когда сервис должен быть проинициализирован сразу при настройке другого компонента.
Сигнатура:
Пример:
service.setService
Метод позволяет связать конструктор с уже существующим экземпляром. Может быть использован для подмены зависимостей в тестах или для внедрения экземпляров, созданных вне контейнера.
Сигнатура:
Пример:
DebuggableService
Данный сервис наследует класс и использует композицию
для получения функциональности класса .
(см. подробнее @e22m4u/js-debug раздел «Класс Debuggable»)
Тесты
Лицензия
MIT