Что такое паттерн Singleton?

«Что такое паттерн Singleton?» — вопрос из категории Паттерны, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Singleton (Одиночка) — это порождающий шаблон проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру.

Зачем он нужен в Node.js? В Node.js модули по умолчанию являются синглтонами (кэшируются после первого require). Однако паттерн полезен, когда нужно явно контролировать процесс создания единственного экземпляра класса, например, для управления подключением к базе данных, конфигурацией или логгером.

Классическая реализация в JavaScript (ES6+):

class DatabaseConnection {
  constructor(config) {
    if (DatabaseConnection.instance) {
      return DatabaseConnection.instance;
    }
    // Имитация сложной инициализации подключения
    this.connectionString = config.connectionString;
    this.isConnected = false;
    this.connect();
    DatabaseConnection.instance = this;
  }

  connect() {
    console.log(`Устанавливается подключение к ${this.connectionString}...`);
    // Логика подключения...
    this.isConnected = true;
  }

  query(sql) {
    if (!this.isConnected) throw new Error('Нет подключения к БД');
    console.log(`Выполняется запрос: ${sql}`);
    // Логика выполнения запроса...
  }

  // Статический метод для удобного доступа (опционально)
  static getInstance(config) {
    if (!DatabaseConnection.instance) {
      DatabaseConnection.instance = new DatabaseConnection(config);
    }
    return DatabaseConnection.instance;
  }
}

// Использование
const config = { connectionString: 'postgresql://localhost/mydb' };

const db1 = new DatabaseConnection(config); // Создаст экземпляр
const db2 = new DatabaseConnection(config); // Вернет существующий экземпляр
const db3 = DatabaseConnection.getInstance(config); // Вернет тот же экземпляр через статический метод

console.log(db1 === db2 && db2 === db3); // true

Особенности в Node.js:

  • Благодаря модульной системе, часто достаточно экспортировать один экземпляр из файла модуля:
    // logger.js
    class Logger { /* ... */ }
    module.exports = new Logger(); // Все, кто require('./logger'), получат один экземпляр
  • В Node.js нет проблемы многопоточности, поэтому реализация проще, чем в Java/C#.

Недостатки:

  • Усложняет модульное тестирование: Глобальное состояние может приводить к зависимостям между тестами. Решается использованием dependency injection.
  • Скрывает зависимости: Класс, использующий синглтон, имеет скрытую зависимость, что нарушает принцип инверсии зависимостей.

Вывод: Используйте синглтон осознанно, в основном для истинно глобальных, неделимых ресурсов, и помните о его влиянии на тестируемость кода.