Привет команда,
Сегодня я хотел бы рассказать о синглтонах и о том, как мы используем их на ежедневной основе.
Итак, паттерн синглтон позволяет нам создавать единственный экземпляр определенного класса. Для каких целей он может быть полезен? Мы используем их для:
- сервисы обмена данными, которые заботятся о передаче данных в/из базовых сервисов
- сервисы обработки данных, которые могут быть инстанцированы только один раз при запуске приложения
- кэш-сервисы
- цели тестирования
Например, мы решили продолжить работу с ранее описанным кэш-сервисом (https://dev.to/frozer/vanilla-js-data-cache-service-1ei2), по некоторым причинам нам не нужно несколько кэш-сервисов.
кэш-сервисов в нашем приложении, так как же нам создать одиночный?
Давайте начнем с очень простого кода для создания синглтона:
class SingletoneService {
static instance;
getInstance(args) {
if (!SingletoneService.instance) {
SingletoneService.instance = new SingletoneService(...args);
}
return SingletoneService.instance;
}
constructor(args) {
// do something with args
}
doSomething() {
// do something
}
}
Итак, как это работает? В основной программе мы можем создать экземпляр синглтона, вызвав этот метод getInstance с аргументами (если они нам нужны):
function main() {
const instance = SingletoneService.getInstance();
instance.doSomething();
}
main();
Вызов метода getInstance проверяет наличие значения статического поля экземпляра класса SingletoneService, а затем инстанцирует новый объект на основе этого класса с помощью ключевого слова new. Если он существует, то просто возвращает существующий экземпляр.
Теперь, когда черновая реализация закончена, попробуйте перенести эту функциональность в наш CacheService:
class SomeServiceWithDataCache {
static instance;
getInstance(args) {
if (!SomeServiceWithDataCache.instance) {
SomeServiceWithDataCache.instance = new SomeServiceWithDataCache(...args);
}
return SomeServiceWithDataCache.instance;
}
constructor() {
this.cache = {
isLoading: false,
expire: 0,
data: null
};
this.cacheSubscriptions = [];
}
...
}
Также вы можете использовать синглтоны для инъекции зависимостей в ваш класс:
class DataProcessingService {
// use existing DataCacheService instance by default
constructor(cacheService = DataCacheService.getInstance()) {
// do something in constructor)
}
...
}
Что позволяет реализовать изоляцию кода и принцип Open-Closed.