Factory паттерн

Суть Factory-подхода в JavaScript

Factory-паттерн представляет собой архитектурный подход, при котором создание объектов выносится в отдельную функцию или слой абстракции. Вместо прямого использования конструктора или оператора new код получает готовый объект через фабрику, которая инкапсулирует логику выбора и конфигурации.

Ключевая особенность заключается в том, что фабрика не просто создаёт объект, а принимает решения о его конкретной реализации на основе входных параметров, окружения или состояния приложения.

Основные характеристики:

  • скрытие деталей инициализации объектов;
  • централизованное управление конфигурацией;
  • возможность подмены реализации без изменения клиентского кода;
  • унификация интерфейса создаваемых объектов.

В контексте ECMAScript Internationalization API фабричный подход проявляется естественным образом, поскольку большинство его сущностей создаются через конструкторы с конфигурационными параметрами, формируя предсказуемые и переиспользуемые экземпляры форматирования.


Intl API как набор фабрик форматирования

Intl API в JavaScript предоставляет набор специализированных конструкторов, каждый из которых фактически реализует фабричную модель:

  • Intl.NumberFormat
  • Intl.DateTimeFormat
  • Intl.Collator
  • Intl.PluralRules
  • Intl.RelativeTimeFormat
  • Intl.ListFormat

Каждый из этих конструкторов не просто создаёт объект, а формирует конфигурированный форматтер, адаптированный под локаль и правила языка.

Пример фабричного поведения NumberFormat

const formatter = new Intl.NumberFormat('ru-RU', {
  style: 'currency',
  currency: 'RUB'
});

formatter.format(123456.78); // "123 456,78 ₽"

Здесь Intl.NumberFormat выступает фабрикой, которая на основании параметров возвращает объект форматирования, скрывающий внутреннюю логику локализации чисел.


Абстракция создания через Intl.NumberFormat

Factory-паттерн особенно заметен в работе с числами, поскольку форматирование зависит от множества факторов:

  • локаль пользователя;
  • тип отображения (валюта, процент, единицы измерения);
  • точность и округление;
  • стиль отображения.

Фабричный подход позволяет инкапсулировать эти параметры:

function createCurrencyFormatter(locale, currency) {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency
  });
}

const usdFormatter = createCurrencyFormatter('en-US', 'USD');
const eurFormatter = createCurrencyFormatter('de-DE', 'EUR');

Такая функция-фабрика устраняет дублирование конфигурации и централизует логику создания форматтеров.


Factory-подход в DateTimeFormat

Intl.DateTimeFormat демонстрирует ещё более яркое применение фабричной модели, поскольку форматирование дат зависит от культурных и региональных соглашений.

const ruFormatter = new Intl.DateTimeFormat('ru-RU', {
  dateStyle: 'full',
  timeStyle: 'short'
});

const jpFormatter = new Intl.DateTimeFormat('ja-JP', {
  dateStyle: 'long'
});

Каждый вызов конструктора возвращает специализированный объект, который уже содержит всю необходимую информацию для преобразования даты.

Фабричный характер проявляется в том, что:

  • клиентский код не знает, как именно формируется строка даты;
  • логика локализации скрыта внутри реализации;
  • объект сразу готов к использованию без дополнительной настройки.

Collator как фабрика правил сортировки

Intl.Collator предоставляет механизм сравнения строк с учётом языковых правил. Это один из наиболее показательных примеров фабрики в Intl API.

const collator = new Intl.Collator('ru', {
  sensitivity: 'base'
});

['ё', 'е', 'ж'].sort(collator.compare);

Метод compare является результатом фабричной конфигурации, где:

  • определяется язык;
  • задаются правила чувствительности;
  • создаётся оптимизированная функция сравнения.

Фактически Intl.Collator возвращает не просто объект, а стратегию сравнения строк, что соответствует расширенному варианту Factory-паттерна — фабрике стратегий.


Построение собственной фабрики на базе Intl API

Использование фабрик поверх Intl API позволяет формировать архитектурно чистые слои локализации.

Базовая структура фабрики форматтеров

const formattersFactory = {
  number(locale) {
    return new Intl.NumberFormat(locale);
  },

  currency(locale, currency) {
    return new Intl.NumberFormat(locale, {
      style: 'currency',
      currency
    });
  },

  date(locale, options) {
    return new Intl.DateTimeFormat(locale, options);
  }
};

Такой подход позволяет централизовать создание всех форматтеров и управлять ими из одного места.


Расширенные фабрики с кэшированием

Intl объекты являются тяжёлыми в создании при массовом использовании, поэтому фабричный слой часто дополняется кэшированием.

const cache = new Map();

function getNumberFormatter(locale, options) {
  const key = JSON.stringify({ locale, options });

  if (cache.has(key)) {
    return cache.get(key);
  }

  const formatter = new Intl.NumberFormat(locale, options);
  cache.set(key, formatter);

  return formatter;
}

Такой подход:

  • уменьшает количество повторных созданий объектов;
  • повышает производительность при массовом форматировании;
  • сохраняет неизменность конфигурации.

Фабрика как слой адаптации локали

В реальных приложениях фабрика часто служит промежуточным слоем между системой и пользовательскими настройками.

function createAppFormatters(userSettings) {
  const locale = userSettings.locale || 'en-US';

  return {
    price: new Intl.NumberFormat(locale, {
      style: 'currency',
      currency: userSettings.currency
    }),

    date: new Intl.DateTimeFormat(locale, {
      dateStyle: 'medium'
    }),

    list: new Intl.ListFormat(locale, {
      style: 'long',
      type: 'conjunction'
    })
  };
}

Такой слой позволяет:

  • централизовать локализацию;
  • привязать форматтеры к пользовательскому профилю;
  • обеспечить единообразие отображения данных.

Factory-подход в PluralRules и RelativeTimeFormat

Intl.PluralRules и Intl.RelativeTimeFormat расширяют фабричную концепцию за счёт генерации вычислительных стратегий.

const pluralRules = new Intl.PluralRules('ru-RU');
pluralRules.select(5); // "many"
const rtf = new Intl.RelativeTimeFormat('ru', { numeric: 'auto' });
rtf.format(-1, 'day'); // "вчера"

Здесь фабрика создаёт объект, который:

  • содержит языковую модель правил;
  • инкапсулирует алгоритмы выбора формы;
  • предоставляет метод вычисления результата.

Композиция фабрик и архитектурные паттерны

Factory-паттерн в связке с Intl API часто комбинируется с другими архитектурными подходами:

  • Strategy — выбор форматтера в зависимости от типа данных;
  • Singleton-кэш — повторное использование экземпляров Intl;
  • Facade — упрощённый интерфейс над набором форматтеров;
  • Adapter — приведение разных локалей к единому интерфейсу приложения.

Пример композиции:

class LocalizationService {
  constructor(locale) {
    this.locale = locale;

    this.number = new Intl.NumberFormat(locale);
    this.date = new Intl.DateTimeFormat(locale);
    this.list = new Intl.ListFormat(locale);
  }

  formatPrice(value, currency) {
    return new Intl.NumberFormat(this.locale, {
      style: 'currency',
      currency
    }).format(value);
  }
}

Ошибки при использовании фабричного подхода с Intl

Неправильное применение фабрик часто приводит к избыточной сложности:

  • создание новых Intl объектов при каждом вызове форматирования;
  • отсутствие кэширования при высокочастотных операциях;
  • дублирование конфигураций в разных частях системы;
  • смешивание бизнес-логики и логики локализации.

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


Производительность и повторное использование экземпляров

Intl объекты оптимизированы для повторного использования, поэтому фабричный слой должен учитывать:

  • создание форматтера один раз на конфигурацию;
  • хранение экземпляров в контексте приложения;
  • минимизацию динамической генерации.

Типичная оптимизация:

const numberFormatter = new Intl.NumberFormat('ru-RU');

function format(value) {
  return numberFormatter.format(value);
}

Такой подход снижает накладные расходы и сохраняет архитектурную чистоту.


Фабрика как основа масштабируемой интернационализации

В крупных приложениях фабричный слой над Intl API становится центральным элементом системы локализации. Он обеспечивает:

  • единое место создания всех форматтеров;
  • согласованность правил отображения;
  • возможность масштабирования на новые локали;
  • предсказуемость поведения форматирования.

Фабричная модель превращает Intl API из набора отдельных инструментов в структурированную систему генерации локализованных представлений данных.