Вы когда-нибудь писали код, а через месяц не могли понять, что там происходит? Или добавляли новую функцию, и всё ломалось? Паттерны проектирования — это проверенные рецепты, которые помогают избежать такого хаоса. В этой статье разберём самые полезные паттерны в JavaScript на простых примерах. Без зауми, только практика.
Что такое паттерны проектирования и зачем они нужны
Паттерн проектирования — это типовое решение частой проблемы. Как рецепт в кулинарной книге: вы не изобретаете борщ заново, а берёте проверенный рецепт и адаптируете под свои продукты. В программировании паттерны экономят время, делают код понятнее для других и упрощают поддержку.
В JavaScript паттерны особенно полезны, потому что язык гибкий. Можно писать как угодно, но без структуры код быстро превращается в спагетти. Паттерны дают эту структуру.
Singleton: один на всех
Синглтон гарантирует, что у класса будет только один экземпляр, и предоставляет глобальную точку доступа к нему. В JavaScript это часто используют для подключения к базе данных, конфигураций или логгеров.
Пример на JavaScript:
class Database {
constructor() {
if (Database.instance) {
return Database.instance;
}
this.connection = 'connected';
Database.instance = this;
}
query(sql) {
console.log(`Выполняю запрос: ${sql}`);
}
}
const db1 = new Database();
const db2 = new Database();
console.log(db1 === db2); // true
Как видите, сколько бы раз вы ни вызывали new Database(), вы всегда получаете один и тот же объект. Удобно, когда нужно разделять состояние между разными частями приложения.
Но будьте осторожны: синглтон создаёт глобальное состояние, а это может усложнить тестирование. Используйте его только там, где действительно нужен один экземпляр.
Factory: создаём объекты, не зная деталей
Фабрика — это паттерн, который делегирует создание объектов подклассам или отдельным методам. Вы просто говорите: «Дай мне транспортное средство», а фабрика решает, что именно вернуть — машину, мотоцикл или велосипед.
Пример:
class Car {
drive() { console.log('Еду на машине'); }
}
class Bike {
drive() { console.log('Еду на велосипеде'); }
}
class VehicleFactory {
createVehicle(type) {
switch(type) {
case 'car': return new Car();
case 'bike': return new Bike();
default: throw new Error('Неизвестный тип');
}
}
}
const factory = new VehicleFactory();
const myCar = factory.createVehicle('car');
myCar.drive(); // Еду на машине
Фабрика полезна, когда логика создания объекта сложная или зависит от условий. Она изолирует код создания от остальной программы.
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 {
update(data) {
console.log(`Получено: ${data}`);
}
}
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.notify('Привет, мир!');
Наблюдатель отлично подходит для реализации подписок, обработки пользовательских действий и связи между компонентами.
Module: прячем внутренности
Модуль — это способ инкапсулировать код, скрывая детали реализации и предоставляя только публичный интерфейс. В JavaScript модули можно создавать с помощью замыканий или ES6-модулей.
Пример с замыканием:
const counterModule = (function() {
let count = 0;
function increment() {
count++;
}
function getCount() {
return count;
}
return {
increment,
getCount
};
})();
counterModule.increment();
console.log(counterModule.getCount()); // 1
Переменная count недоступна снаружи, но мы можем управлять ею через методы. Это защищает данные от случайного изменения.
Сравнение паттернов: когда что использовать
Чтобы выбрать подходящий паттерн, ориентируйтесь на задачу. Вот краткая таблица:
| Паттерн | Когда использовать | Пример |
|---|---|---|
| Singleton | Нужен единственный экземпляр (конфиг, логгер) | Подключение к БД |
| Factory | Создание объектов с разной логикой | Фабрика UI-компонентов |
| Observer | Реакция на события, подписки | Обработка кликов, стримы |
| Module | Инкапсуляция, скрытие деталей | Библиотеки, утилиты |
Не бойтесь комбинировать паттерны. Например, фабрика может использовать синглтон для создания единственного экземпляра какого-то сервиса.
Заключение
Паттерны проектирования — это не серебряная пуля, но мощный инструмент в руках разработчика. Они помогают писать код, который легко читать, тестировать и расширять. В JavaScript особенно полезны Singleton, Factory, Observer и Module. Начните с одного паттерна, примените его в реальном проекте, и вы почувствуете разницу. Главное — не усложняйте там, где можно обойтись простым решением.
Помните: паттерны — это язык общения между разработчиками. Зная их, вы быстрее поймёте чужой код и сможете объяснить свой.



