← Назад к вопросам

Что такое Singletone?

2.0 Middle🔥 191 комментариев
#Архитектура и паттерны#ООП

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Singleton — это паттерн проектирования (design pattern), который гарантирует, что класс имеет только один экземпляр и предоставляет глобальную точку доступа к этому экземпляру. Это один из самых простых и часто используемых паттернов в разработке.

Проблема, которую решает Singleton

Представьте, что вы работаете с базой данных. Если каждый раз при запросе создавать новое соединение, это потребует много памяти, замедлит приложение и может привести к exhaustion ресурсов. Singleton решает эту проблему, обеспечивая единственный экземпляр класса.

Реализация в JavaScript/Node.js

Классический способ (ES5)

class Database {
  constructor() {
    if (Database.instance) {
      return Database.instance;
    }
    this.connection = null;
    Database.instance = this;
  }

  connect() {
    if (!this.connection) {
      this.connection = new Pool({
        connectionString: process.env.DATABASE_URL
      });
      console.log('Database connected');
    }
    return this.connection;
  }
}

const db1 = new Database();
const db2 = new Database();
console.log(db1 === db2); // true

Использование замыкания (более чистый подход)

class Database {
  constructor() {
    this.connection = null;
  }

  connect() {
    if (!this.connection) {
      this.connection = new Pool({
        connectionString: process.env.DATABASE_URL
      });
    }
    return this.connection;
  }
}

const dbInstance = (() => {
  let instance = null;
  
  return {
    getInstance: () => {
      if (!instance) {
        instance = new Database();
      }
      return instance;
    }
  };
})();

const db = dbInstance.getInstance();
const db2 = dbInstance.getInstance();
console.log(db === db2); // true

Современный способ (ES6 Module) — РЕКОМЕНДУЕТСЯ

class Database {
  constructor() {
    this.connection = null;
  }

  connect() {
    if (!this.connection) {
      this.connection = new Pool({
        connectionString: process.env.DATABASE_URL
      });
      console.log('Connected to database');
    }
    return this.connection;
  }

  query(sql, params) {
    return this.connection.query(sql, params);
  }
}

export default new Database();
import database from './database.js';

database.connect();
const result = await database.query('SELECT * FROM users');

Практические примеры Singleton в Node.js

Logger

class Logger {
  constructor() {
    if (Logger.instance) {
      return Logger.instance;
    }
    this.logs = [];
    Logger.instance = this;
  }

  log(message) {
    this.logs.push({
      message,
      timestamp: new Date()
    });
    console.log(message);
  }
}

export default new Logger();

Configuration Manager

class Config {
  constructor() {
    if (Config.instance) {
      return Config.instance;
    }
    this.env = process.env.NODE_ENV || 'development';
    this.port = process.env.PORT || 3000;
    this.dbUrl = process.env.DATABASE_URL;
    Config.instance = this;
  }

  get(key) {
    return this[key];
  }
}

export default new Config();

Redis Cache

class RedisClient {
  constructor() {
    if (RedisClient.instance) {
      return RedisClient.instance;
    }
    this.client = redis.createClient();
    RedisClient.instance = this;
  }

  async get(key) {
    return await this.client.get(key);
  }

  async set(key, value) {
    await this.client.set(key, value);
  }
}

export default new RedisClient();

Преимущества

  • Контролируемый доступ к единственному экземпляру
  • Ленивая инициализация — объект создается только при первом использовании
  • Экономия памяти — нет дублирующихся объектов
  • Потокобезопасность при правильной реализации

Недостатки

  • Глобальное состояние — может усложнить тестирование
  • Скрытые зависимости — класс зависит от Singleton
  • Сложнее отследить происходящее в коде

Когда использовать Singleton?

  • Подключение к базе данных
  • Logger
  • Configuration Manager
  • Кэш (Redis, Memcached)
  • Pool соединений
  • Event Bus

Когда НЕ использовать?

  • Когда нужна гибкость и разные конфигурации
  • Когда нужны независимые экземпляры для разных задач
  • Для unit тестирования (усложняет моки и стабы)