Паттерны проектирования — это переиспользуемые решения часто встречающихся проблем в программировании. Они представляют собой не готовый код, а концепции или шаблоны, которые можно адаптировать под конкретную задачу. Их принято делить на три основные группы:
Порождающие (Creational): Отвечают за гибкое создание объектов.
Структурные (Structural): Определяют, как объекты могут быть объединены для формирования более крупных структур.
Поведенческие (Behavioral): Отвечают за эффективное взаимодействие между объектами.
Гарантирует, что у модуля есть только один экземпляр, и предоставляет глобальную точку доступа к нему. В функциональном подходе это достигается с помощью замыкания.
Особенность: Полезен для управления общим состоянием (например, конфигурация приложения, сервис логирования).
const AppConfig = (() => {
let instance;
function createInstance() {
const config = { theme: 'dark' };
return {
getConfig: () => config,
};
}
return {
getInstance: () => {
if (!instance) {
instance = createInstance();
}
return instance;
},
};
})();
const config1 = AppConfig.getInstance();
const config2 = AppConfig.getInstance();
console.log(config1 === config2); // trueПозволяет динамически добавлять объектам новую функциональность, оборачивая их в функции-декораторы.
Особенность: Гибкая альтернатива наследованию. Идеально подходит для расширения функциональности без изменения исходного объекта.
const createCoffee = () => ({
cost: () => 5,
});
// Декоратор
const withMilk = (coffee) => ({
...coffee,
cost: () => coffee.cost() + 2,
});
// Декоратор
const withSugar = (coffee) => ({
...coffee,
cost: () => coffee.cost() + 1,
});
let myCoffee = createCoffee();
myCoffee = withMilk(myCoffee);
myCoffee = withSugar(myCoffee);
console.log(myCoffee.cost()); // 8 (5 + 2 + 1)Предоставляет унифицированную и упрощенную функцию-фасад для взаимодействия со сложной подсистемой.
Особенность: Скрывает сложность. Например, можно создать фасад для работы с браузерными API (DOM, Fetch, LocalStorage).
// Сложная подсистема
const domApi = {
createElement: (tag) => { /* ... */ },
addStyle: (element, styles) => { /* ... */ },
};
const fetchApi = {
get: (url) => { /* ... */ },
};
// Фасад
const createAppFacade = () => ({
fetchAndDisplay: (url, elementId) => {
const data = fetchApi.get(url);
const element = domApi.createElement('div');
// ... логика отображения
}
});
const app = createAppFacade();
// app.fetchAndDisplay('/api/data', '#root');Создает механизм подписки, позволяющий одним объектам (наблюдателям) следить за изменениями в другом объекте (субъекте).
Особенность: Основа реактивного программирования. Используется в управлении состоянием (Redux, MobX) и событийной модели в браузере.
const createNewsPublisher = () => {
let subscribers = [];
return {
subscribe: (observer) => {
subscribers.push(observer);
},
unsubscribe: (observer) => {
subscribers = subscribers.filter(obs => obs !== observer);
},
notify: (news) => {
subscribers.forEach(observer => observer.update(news));
},
};
};
const createReader = (name) => ({
update: (news) => {
console.log(`${name} прочитал новость: ${news}`);
},
});
const publisher = createNewsPublisher();
const reader1 = createReader('Иван');
const reader2 = createReader('Мария');
publisher.subscribe(reader1);
publisher.subscribe(reader2);
publisher.notify('Вышла новая версия JavaScript!');
// Иван прочитал новость: Вышла новая версия JavaScript!
// Мария прочитал новость: Вышла новая версия JavaScript!Определяет семейство схожих алгоритмов (функций) и позволяет передавать их в качестве аргумента, делая их взаимозаменяемыми.
Особенность: Позволяет менять логику «на лету». Например, выбор способа сортировки или метода валидации формы.
const validate = (strategy, value) => {
return strategy(value);
};
const isRequired = (value) => !!value;
const isEmail = (value) => /@/.test(value);
console.log(validate(isRequired, '')); // false
console.log(validate(isEmail, 'test@test.com')); // true