Комментарии (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 тестирования (усложняет моки и стабы)