← Назад к вопросам

Что такое Decorator?

1.8 Middle🔥 161 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Decorator

Decorator (Декоратор) — это паттерн проектирования, который позволяет добавлять новые функции к объектам динамически, не изменяя их структуру. В JavaScript это функция, которая обёртывает другую функцию или класс и расширяет его поведение.

Типы декораторов

Функциональные декораторы — оборачивают функции:

function log(fn) {
  return function(...args) {
    console.log('Вызов', fn.name, 'с аргументами', args);
    return fn.apply(this, args);
  };
}

function add(a, b) {
  return a + b;
}

const loggedAdd = log(add);
loggedAdd(2, 3); // Вывод: Вызов add с аргументами [2, 3]

Классовые декораторы (TypeScript / JavaScript экспериментальный синтаксис):

function Controller(prefix: string) {
  return function(constructor) {
    constructor.prototype.baseUrl = prefix;
    return constructor;
  };
}

@Controller('/api/users')
class UserController {
  getAll() { /* ... */ }
}

Декораторы методов:

function Memoize(target, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  const cache = new Map();

  descriptor.value = function(...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = originalMethod.apply(this, args);
    cache.set(key, result);
    return result;
  };
  return descriptor;
}

class Calculator {
  @Memoize
  expensive(n: number) {
    return n * 2; // Вычисляется один раз
  }
}

Практические примеры в Node.js

Express middleware как декоратор:

function authenticate(req, res, next) {
  if (!req.headers.authorization) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  next();
}

app.get('/admin', authenticate, (req, res) => {
  res.json({ message: 'Admin area' });
});

Декоратор для кэширования в NestJS:

import { CacheKey, Cacheable } from '@nestjs/cache-manager';

@Cacheable()
@CacheKey('users')
@Get('/users')
async getUsers() {
  return this.userService.findAll();
}

Собственный декоратор для retry логики:

function retry(attempts = 3) {
  return function(target, propertyKey, descriptor) {
    const originalMethod = descriptor.value;

    descriptor.value = async function(...args) {
      for (let i = 0; i < attempts; i++) {
        try {
          return await originalMethod.apply(this, args);
        } catch (error) {
          if (i === attempts - 1) throw error;
          console.log('Попытка', i + 1, 'не удалась, повторяю...');
        }
      }
    };
    return descriptor;
  };
}

class ApiClient {
  @retry(3)
  async fetchData() {
    return fetch('https://api.example.com/data');
  }
}

Зачем использовать декораторы

Избежать дублирования кода — логирование, валидация, кэширование можно применить ко множеству функций через декоратор.

Разделение ответственности — основная логика отделена от сквозных задач (cross-cutting concerns).

Конфигурируемость — декоратор может принимать параметры.

Читаемость — @log, @Cacheable, @Authenticate явно показывают, что происходит.

Различие от middleware

Middleware — обрабатывает запросы/ответы, работает на уровне HTTP.

Decorator — работает на уровне функции/класса, не привязан к HTTP.

Декораторы — мощный инструмент для расширения функциональности без изменения исходного кода.