Стратегия и фабричные паттерны

Riot.js — легковесный фреймворк для создания UI-компонентов с реактивными данными и минимальным количеством кода. В крупных проектах архитектура компонентов может быть организована с использованием паттернов проектирования, таких как Стратегия и Фабрика, что упрощает поддержку и расширяемость приложений.


Паттерн Стратегия

Паттерн Стратегия позволяет определить семейство алгоритмов, инкапсулировать каждый из них и делать их взаимозаменяемыми. В контексте Riot.js стратегии полезны при работе с компонентами, которые должны вести себя по-разному в зависимости от внешних условий или настроек.

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

Рассмотрим компонент, который рендерит список с разной логикой сортировки:

// Определение стратегий сортировки
const sortStrategies = {
  byName: (items) => items.sort((a, b) => a.name.localeCompare(b.name)),
  byDate: (items) => items.sort((a, b) => new Date(a.date) - new Date(b.date)),
  byPriority: (items) => items.sort((a, b) => b.priority - a.priority)
};

// Компонент Riot
<item-list>
  <ul>
    <li each={item in sortedItems}>{item.name} - {item.date} - {item.priority}</li>
  </ul>

  this.on('mount', () => {
    this.sortedItems = sortStrategies.byName(this.items);
  });

  updateSorting(strategy) {
    this.sortedItems = sortStrategies[strategy](this.items);
    this.update();
  }
</item-list>

Ключевые моменты:

  • Алгоритмы сортировки инкапсулированы в объект sortStrategies.
  • В компоненте можно динамически менять стратегию через метод updateSorting.
  • Не требуется изменять код компонента при добавлении новых стратегий — достаточно расширить объект sortStrategies.

Фабричный паттерн

Фабричный метод позволяет создавать объекты без явного указания конкретного класса. В Riot.js это удобно для динамического создания компонентов с разными конфигурациями или типами отображения.

Пример фабрики компонентов

// Фабрика для создания различных карточек
function cardFactory(type, props) {
  switch(type) {
    case 'user':
      return riot.component(UserCard, props);
    case 'product':
      return riot.component(ProductCard, props);
    case 'notification':
      return riot.component(NotificationCard, props);
    default:
      throw new Error('Unknown card type: ' + type);
  }
}

// Использование фабрики
const cards = [
  cardFactory('user', { name: 'Иван', age: 28 }),
  cardFactory('product', { title: 'Ноутбук', price: 1200 }),
  cardFactory('notification', { message: 'Новая активность' })
];

Особенности:

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

Сочетание стратегии и фабрики

Часто эти паттерны комбинируются для максимальной гибкости. Например, фабрика может создавать компонент с заранее выбранной стратегией поведения:

function sortedListFactory(type, items) {
  const strategies = {
    simple: (items) => items,
    reverse: (items) => items.slice().reverse(),
    custom: (items) => items.sort((a, b) => a.value - b.value)
  };

  return riot.component(SortedList, {
    items,
    strategy: strategies[type]
  });
}

const list = sortedListFactory('reverse', [{value:3},{value:1},{value:2}]);

Преимущества такого подхода:

  • Компонент становится полностью конфигурируемым.
  • Стратегии можно изменять без модификации основного компонента.
  • Поддерживается принцип открытости/закрытости (Open/Closed Principle) — новые типы поведения добавляются легко.

Практические рекомендации

  • Для стратегий использовать объекты или Map, чтобы легко добавлять новые алгоритмы.
  • Для фабрик обеспечивать единый интерфейс создания компонентов с обязательной проверкой входных данных.
  • Избегать чрезмерной вложенности фабрик и стратегий — при больших проектах рекомендуется использовать отдельные модули.
  • Стратегии лучше держать чистыми функциями без побочных эффектов, чтобы Riot.js мог корректно отслеживать обновления данных.

Структурирование компонентов с использованием паттернов Стратегия и Фабрика повышает модульность и масштабируемость приложений на Riot.js, позволяет создавать гибкие и легко расширяемые интерфейсы без дублирования кода.