Skip to main content
Практика завдань

Які найбільш поширені шаблони проектування в Node.js?

Шаблони проектування в Node.js

Шаблони проектування — це повторно використовувані рішення для поширених проблем програмування. Node.js має кілька шаблонів, які особливо актуальні через свою асинхронну, подієву природу.


1. Шаблон модуля

Модулі Node.js забезпечують природну інкапсуляцію:

js
// counter.js — інкапсульований стан let count = 0; module.exports = { increment: () => ++count, decrement: () => --count, getCount: () => count };
js
const counter = require('./counter'); counter.increment(); console.log(counter.getCount()); // 1

2. Шаблон синглтона

Оскільки Node.js кешує require(), модулі природно є синглтонами:

js
// database.js class Database { constructor() { if (Database.instance) return Database.instance; this.connection = null; Database.instance = this; } async connect(url) { if (!this.connection) { this.connection = await createConnection(url); } return this.connection; } } module.exports = new Database();
js
// Обидва повертають один і той же екземпляр const db1 = require('./database'); const db2 = require('./database'); console.log(db1 === db2); // true

3. Шаблон спостерігача (EventEmitter)

Основний елемент Node.js — широко використовується в потоках, HTTP та кастомних подіях:

js
const EventEmitter = require('events'); class OrderService extends EventEmitter { placeOrder(order) { // Бізнес-логіка... this.emit('orderPlaced', order); } } const orderService = new OrderService(); // Підписники orderService.on('orderPlaced', (order) => { emailService.sendConfirmation(order); }); orderService.on('orderPlaced', (order) => { inventoryService.updateStock(order); }); orderService.placeOrder({ id: 1, item: 'Laptop' });

4. Фабричний шаблон

Створення об'єктів без розкриття логіки створення:

js
class DatabaseFactory { static create(type) { switch (type) { case 'postgres': return new PostgresAdapter(); case 'mongodb': return new MongoAdapter(); case 'redis': return new RedisAdapter(); default: throw new Error(`Невідомий тип бази даних: ${type}`); } } } const db = DatabaseFactory.create(process.env.DB_TYPE);

5. Шаблон проміжного програмного забезпечення (Chain of Responsibility)

Основний шаблон в Express.js та NestJS:

js
class MiddlewareChain { constructor() { this.middlewares = []; } use(fn) { this.middlewares.push(fn); return this; } async execute(context) { let index = 0; const next = async () => { if (index < this.middlewares.length) { const middleware = this.middlewares[index++]; await middleware(context, next); } }; await next(); } } const chain = new MiddlewareChain(); chain.use(async (ctx, next) => { console.log('Перевірка автентифікації'); ctx.user = { id: 1 }; await next(); }); chain.use(async (ctx, next) => { console.log(`Користувач: ${ctx.user.id}`); await next(); });

6. Шаблон стратегії

Змінні алгоритми під час виконання:

js
class PaymentProcessor { constructor(strategy) { this.strategy = strategy; } async pay(amount) { return this.strategy.process(amount); } } const stripeStrategy = { process: (amount) => stripe.charges.create({ amount }) }; const paypalStrategy = { process: (amount) => paypal.payment.create({ amount }) }; // Використання Stripe const processor = new PaymentProcessor(stripeStrategy); await processor.pay(100);

7. Шаблон репозиторію

Абстрагує доступ до даних від бізнес-логіки:

js
class UserRepository { constructor(database) { this.db = database; } async findById(id) { return this.db.query('SELECT * FROM users WHERE id = $1', [id]); } async create(userData) { return this.db.query( 'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *', [userData.name, userData.email] ); } async findByEmail(email) { return this.db.query('SELECT * FROM users WHERE email = $1', [email]); } }

Підсумок шаблонів

ШаблонВикористання в Node.js
МодульІнкапсуляція, організація коду
СинглтонЗ'єднання з БД, конфігурація, кеші
СпостерігачПодієва комунікація
ФабрикаАбстракція створення об'єктів
Проміжне ПЗПайплайни обробки запитів
СтратегіяЗмінні алгоритми
РепозиторійАбстракція доступу до даних
ДекораторРозширення поведінки (NestJS)
ПроксіКешування, логування, контроль доступу

Порада: Не намагайтеся нав'язувати шаблони, де вони не підходять. Система модулів Node.js та подієва природа вже сприяють чистим шаблонам. Використовуйте їх, коли вони вирішують реальні проблеми, а не для теоретичної чистоти.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань