Вы когда-нибудь писали код, а потом через месяц смотрели на него и думали: «Что за каша?». Или переделывали одну и ту же логику в разных местах? Знакомо. Паттерны проектирования — это как готовые рецепты для типовых задач. Они помогают структурировать код, делать его понятным и гибким. Сегодня разберем три самых популярных паттерна в JavaScript: Singleton, Factory и Observer. Без заумных слов, только практика.
Паттерн Singleton: когда объект должен быть один
Представьте, что вы пишете приложение для учета пользователей. У вас есть класс, который подключается к базе данных. Если каждый раз создавать новый экземпляр, то соединений будет много, а это медленно. Singleton гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. В JavaScript это реализуется через замыкания или модули.
const Database = (function() {
let instance;
function createInstance() {
return {
connect: function() {
console.log('Подключение к базе данных');
},
query: function(sql) {
console.log('Выполнение запроса: ' + sql);
}
};
}
return {
getInstance: function() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const db1 = Database.getInstance();
const db2 = Database.getInstance();
console.log(db1 === db2); // trueЛайфхак: В современных проектах для Singleton используйте ES6 модули — они сами создают один экземпляр при импорте.
Паттерн Factory: фабрика объектов без лишнего кода
Допустим, вы создаете игру. Есть разные типы врагов: орки, эльфы, драконы. Каждый тип имеет свои характеристики. Если писать отдельный класс для каждого, код раздуется. Factory позволяет создавать объекты на основе переданного типа, скрывая логику создания. В JavaScript это часто реализуется через функцию, которая возвращает объект.
function EnemyFactory(type, level) {
const enemies = {
orc: { health: 100, damage: 20, color: 'green' },
elf: { health: 70, damage: 30, color: 'blue' },
dragon: { health: 300, damage: 50, color: 'red' }
};
const base = enemies[type] || enemies.orc;
return {
type: type,
health: base.health * level,
damage: base.damage * level,
color: base.color,
attack: function() {
console.log(this.type + ' атакует с уроном ' + this.damage);
}
};
}
const orc = EnemyFactory('orc', 2);
const dragon = EnemyFactory('dragon', 1);
orc.attack(); // orc атакует с уроном 40Лайфхак: Factory хорошо комбинируется с паттерном Strategy, когда нужно менять поведение объектов на лету.
Паттерн Observer: подписка на события
Представьте, что у вас есть онлайн-магазин. Когда товар заканчивается, нужно уведомить всех, кто его ждет. Observer реализует механизм подписки: один объект (издатель) уведомляет множество подписчиков при изменении состояния. В JavaScript это основа событийной модели.
class Subject {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
}
unsubscribe(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(this.name + ' получил уведомление: ' + data);
}
}
const subject = new Subject();
const user1 = new Observer('Иван');
const user2 = new Observer('Мария');
subject.subscribe(user1);
subject.subscribe(user2);
subject.notify('Товар появился в наличии!');
// Иван получил уведомление: Товар появился в наличии!
// Мария получил уведомление: Товар появился в наличии!Лайфхак: В JavaScript для Observer часто используют встроенные EventTarget или библиотеки вроде RxJS, но простая реализация помогает понять суть.
Сравнение паттернов: когда что использовать
| Паттерн | Когда применять | Примеры |
|---|---|---|
| Singleton | Нужен один экземпляр класса | Логгер, конфигурация, подключение к БД |
| Factory | Создание объектов разных типов | Игровые персонажи, виджеты UI |
| Observer | Один ко многим, уведомления | События мыши, подписки на данные |
Что в итоге
Паттерны проектирования — это не магия, а просто проверенные решения. Singleton помогает контролировать ресурсы, Factory упрощает создание объектов, Observer делает код гибким для событий. Начните с этих трех, и ваш JavaScript-код станет чище и понятнее. Помните: не нужно использовать паттерны везде, только там, где они реально облегчают жизнь.
Студия WNDER



